unit libPNG;
{
libPNG Header conversion by Steffen Xonna. (21-03-2008)

http://www.dev-center.de/index.php?cat=header&file=libpng

Below you find an extract of the copyright from the original libPNG header.
For more informations please look in the original libPNG header.

/* png.h - header file for PNG reference library
 *
 * libpng version 1.2.16 - January 31, 2007
 * Copyright (c) 1998-2007 Glenn Randers-Pehrson
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
 *
 * Authors and maintainers:
 *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
 *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
 *  libpng versions 0.97, January 1998, through 1.2.16 - January 31, 2007: Glenn
 *  See also "Contributing Authors", below.
 ...
*/

}

{$IFDEF FPC}
  {$MODE Delphi}

  {$IFDEF CPUI386}
    {$DEFINE CPU386}
    {$ASMMODE INTEL}
  {$ENDIF}

  {$IFNDEF WIN32}
    {$LINKLIB c}
  {$ENDIF}
{$ENDIF}

{$EXTENDEDSYNTAX ON}
{$ALIGN 8}
{$MINENUMSIZE 4}

interface

uses
  Classes, SysUtils, VectorGeometry, GLCrossPlatform;

type
  png_byte =            byte;
  png_int_16 =          smallint;
  png_uint_16 =         word;
  png_int_32 =          integer;
  png_uint_32 =         cardinal;
  png_size_t =          cardinal;
  png_fixed_point =     png_int_32;
  png_char =            AnsiChar;
//  png_void =           nil;

  png_bytep =           ^png_byte;
  png_int_16p =         ^png_int_16;
  png_uint_16p =        ^png_uint_16;
  png_int_32p =         ^png_int_32;
  png_uint_32p =        ^png_uint_32;
  png_fixed_pointp =    ^png_fixed_point;
  png_charp =           pAnsiChar;
  png_const_charp =     pAnsiChar;
  png_voidp =           pointer;
  png_doublep =         ^double;

  png_bytepp =          ^png_bytep;
  png_int_16pp =        ^png_int_16p;
  png_uint_16pp =       ^png_uint_16p;
  png_int_32pp =        ^png_int_32p;
  png_uint_32pp =       ^png_uint_32p;
  png_fixed_pointpp =   ^png_fixed_pointp;
  png_charpp =          ^png_charp;
  png_voidpp =          ^png_voidp;

  png_charppp =         ^png_charpp;

  png_FILE_p =          cardinal;

  { compatibility for C }
  TM = record
    tm_sec: Integer;     { Seconds }
    tm_min: Integer;     { Minutes }
    tm_hour: Integer;    { Hours }
    tm_mday: Integer;    { Day of the month }
    tm_mon: Integer;     { Months }
    tm_year: Integer;    { Years since 1900 }
    tm_wday: Integer;    { Days since Sunday (0 - 6) }
    tm_yday: Integer;    { Day of the year (0 - 365) }
    tm_isdst: Integer;   { Daylight savings time flag }
  end;
  TMp = ^TM;

  time_t = Longint;
  

const
  PNG_LIBPNG_VER_STRING = '1.2.16';
  PNG_HEADER_VERSION_STRING = ' libpng version 1.2.16 - January 31, 2007 (header)'#13#10;

  PNG_LIBPNG_VER_SONUM = 0;
  PNG_LIBPNG_VER_DLLNUM = 13;

  PNG_LIBPNG_VER_MAJOR   =  1;
  PNG_LIBPNG_VER_MINOR   =  2;
  PNG_LIBPNG_VER_RELEASE = 16;

  PNG_LIBPNG_VER = 10216;  { 1.2.16 }



type
{ Three color definitions.  The order of the red, green, and blue, (and the
  exact size) is not important, although the size of the fields need to
  be png_byte or png_uint_16 (as defined below). }

  png_color = record 
    red: png_byte;
    green: png_byte;
    blue: png_byte;
  end;
  png_colorp = ^png_color;
  png_colorpp = ^png_colorp;


  png_color_16 = record
    index: png_byte;       { used for palette files }
    red: png_uint_16;      { for use in red green blue files }
    green: png_uint_16;
    blue: png_uint_16;
    gray: png_uint_16;     { for use in grayscale files }
  end;
  png_color_16p = ^png_color_16;
  png_color_16pp = ^png_color_16p;


  png_color_8 = record
    red: png_byte;      { for use in red green blue files }
    green: png_byte;
    blue: png_byte;
    gray: png_byte;     { for use in grayscale files }
    alpha: png_byte;    { for alpha channel files }
  end;
  png_color_8p = ^png_color_8;
  png_color_8pp = ^png_color_8p;


{ The following two structures are used for the in-core representation
  of sPLT chunks. }

  png_sPLT_entry = record
    red: png_uint_16;
    green: png_uint_16;
    blue: png_uint_16;
    alpha: png_uint_16;
    frequency: png_uint_16;
  end;
  png_sPLT_entryp = ^png_sPLT_entry;
  png_sPLT_entrypp = ^png_sPLT_entryp;


{ When the depth of the sPLT palette is 8 bits, the color and alpha samples
  occupy the LSB of their respective members, and the MSB of each member
  is zero-filled.  The frequency member always occupies the full 16 bits. }

  png_sPLT_t = record
    name: png_charp;            { palette name }
    depth: png_byte;            { depth of palette samples }
    entries: png_sPLT_entryp;   { palette entries }
    nentries: png_int_32;       { number of palette entries }
  end;
  png_sPLT_tp = ^png_sPLT_t;
  png_sPLT_tpp = ^png_sPLT_tp;


{ png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
  and whether that contents is compressed or not.  The "key" field
  points to a regular zero-terminated C string.  The "text", "lang", and
  "lang_key" fields can be regular C strings, empty strings, or NULL pointers.
  However, the * structure returned by png_get_text() will always contain
  regular zero-terminated C strings (possibly empty), never NULL pointers,
  so they can be safely used in printf() and other string-handling functions. }

  png_text = record
    compression: Integer;    { compression value:
                               -1: tEXt, none
                                0: zTXt, deflate
                                1: iTXt, none
                                2: iTXt, deflate }
    key: png_charp;          { keyword, 1-79 character description of "text" }
    text: png_charp;         { comment, may be an empty string (ie "")
                               or a NULL pointer }
    text_length: png_size_t; { length of the text string }

    itxt_length: png_size_t; { length of the itxt string }
    lang: png_charp;         { language code, 0-79 characters
                               or a NULL pointer }
    lang_key: png_charp;     { keyword translated UTF-8 string, 0 or more
                               chars or a NULL pointer }
  end;
  png_textp = ^png_text;
  png_textpp = ^png_textp;

const
{ Supported compression types for text in PNG files (tEXt, and zTXt).
  The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. }
  PNG_TEXT_COMPRESSION_NONE_WR = -3;
  PNG_TEXT_COMPRESSION_zTXt_WR = -2;
  PNG_TEXT_COMPRESSION_NONE    = -1;
  PNG_TEXT_COMPRESSION_zTXt    =  0;
  PNG_ITXT_COMPRESSION_NONE    =  1;
  PNG_ITXT_COMPRESSION_zTXt    =  2;
  PNG_TEXT_COMPRESSION_LAST    =  3;  { Not a valid value }

type
{ png_time is a way to hold the time in an machine independent way.
  Two conversions are provided, both from time_t and struct tm.  There
  is no portable way to convert to either of these structures, as far
  as I know.  If you know of a portable way, send it to me.  As a side
  note - PNG has always been Year 2000 compliant! }

  png_time = record
    year: png_uint_16; { full year, as in, 1995 }
    month: png_byte;   { month of year, 1 - 12 }
    day: png_byte;     { day of month, 1 - 31 }
    hour: png_byte;    { hour of day, 0 - 23 }
    minute: png_byte;  { minute of hour, 0 - 59 }
    second: png_byte;  { second of minute, 0 - 60 (for leap seconds) }
  end;
  png_timep = ^png_time;
  png_timepp = ^png_timep;


{ png_unknown_chunk is a structure to hold queued chunks for which there is
  no specific support.  The idea is that we can use this to queue
  up private chunks for output even though the library doesn't actually
  know about their semantics. }
  
  png_unknown_chunk = record
    name: array [0..4] of png_byte;
    data: ^png_byte;
    size: png_size_t;

    { libpng-using applications should NOT directly modify this byte. }
    location: png_byte; { mode of operation at read time }
  end;
  png_unknown_chunkp = ^png_unknown_chunk;
  png_unknown_chunkpp = ^png_unknown_chunkp;


{ png_info is a structure that holds the information in a PNG file so
  that the application can find out the characteristics of the image.
  If you are reading the file, this structure will tell you what is
  in the PNG file.  If you are writing the file, fill in the information
  you want to put into the PNG file, then call png_write_info().
  The names chosen should be very close to the PNG specification, so
  consult that document for information about the meaning of each field.
 
  With libpng < 0.95, it was only possible to directly set and read the
  the values in the png_info_struct, which meant that the contents and
  order of the values had to remain fixed.  With libpng 0.95 and later,
  however, there are now functions that abstract the contents of
  png_info_struct from the application, so this makes it easier to use
  libpng with dynamic libraries, and even makes it possible to use
  libraries that don't have all of the libpng ancillary chunk-handing
  functionality.
 
  In any case, the order of the parameters in png_info_struct should NOT
  be changed for as long as possible to keep compatibility with applications
  that use the old direct-access method with png_info_struct.

  The following members may have allocated storage attached that should be
  cleaned up before the structure is discarded: palette, trans, text,
  pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
  splt_palettes, scal_unit, row_pointers, and unknowns.   By default, these
  are automatically freed when the info structure is deallocated, if they were
  allocated internally by libpng.  This behavior can be changed by means
  of the png_data_freer() function.

  More allocation details: all the chunk-reading functions that
  change these members go through the corresponding png_set_*
  functions.  A function to clear these members is available: see
  png_free_data().  The png_set_* functions do not depend on being
  able to point info structure members to any of the storage they are
  passed (they make their own copies), EXCEPT that the png_set_text
  functions use the same storage passed to them in the text_ptr or
  itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
  functions do not make their own copies.}

  png_info = record
    { the following are necessary for every PNG file }
    width: png_uint_32;       { width of image in pixels (from IHDR) }
    height: png_uint_32;      { height of image in pixels (from IHDR) }
    valid: png_uint_32;       { valid chunk data (see PNG_INFO_ below) }
    rowbytes: png_uint_32;    { bytes needed to hold an untransformed row }
    palette: png_colorp;      { array of color values (valid & PNG_INFO_PLTE) }
    num_palette: png_uint_16; { number of color entries in "palette" (PLTE) }
    num_trans: png_uint_16;   { number of transparent palette color (tRNS) }
    bit_depth: png_byte;      { 1, 2, 4, 8, or 16 bits/channel (from IHDR) }
    color_type: png_byte;     { see PNG_COLOR_TYPE_ below (from IHDR) }

    { The following three should have been named *_method not *_type }
    compression_type: png_byte; { must be PNG_COMPRESSION_TYPE_BASE (IHDR) }
    filter_type: png_byte;    { must be PNG_FILTER_TYPE_BASE (from IHDR) }
    interlace_type: png_byte; { One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 }

    { The following is informational only on read, and not used on writes. }
    channels: png_byte;       { number of data channels per pixel (1, 2, 3, 4) }
    pixel_depth: png_byte;    { number of bits per pixel }
    spare_byte: png_byte;     { to align the data, and for future use }
    signature: array[0..7] of png_byte; { magic bytes read by libpng from start of file }

    { The rest of the data is optional.  If you are reading, check the
      valid field to see if the information in these are valid.  If you
      are writing, set the valid field to those chunks you want written,
      and initialize the appropriate fields below. }

    { The gAMA chunk describes the gamma characteristics of the system
      on which the image was created, normally in the range [1.0, 2.5].
      Data is valid if (valid & PNG_INFO_gAMA) is non-zero. }
    gamma: single;  { gamma value of image, if (valid & PNG_INFO_gAMA) }

    { GR-P, 0.96a }
    { Data valid if (valid & PNG_INFO_sRGB) non-zero. }
    srgb_intent: png_byte;  { sRGB rendering intent [0, 1, 2, or 3] }

    { The tEXt, and zTXt chunks contain human-readable textual data in
      uncompressed, compressed, and optionally compressed forms, respectively.
      The data in "text" is an array of pointers to uncompressed,
      null-terminated C strings. Each chunk has a keyword that describes the
      textual data contained in that chunk.  Keywords are not required to be
      unique, and the text string may be empty.  Any number of text chunks may
      be in an image. }

    num_text: Integer;  { number of comments read/to write }
    max_text: integer;  { current size of text array }
    text: png_textp;  { array of comments read/to write }

    { The tIME chunk holds the last time the displayed image data was
      modified.  See the png_time struct for the contents of this struct. }
    mod_time: png_time;

    { The sBIT chunk specifies the number of significant high-order bits
      in the pixel data.  Values are in the range [1, bit_depth], and are
      only specified for the channels in the pixel data.  The contents of
      the low-order bits is not specified.  Data is valid if
      (valid & PNG_INFO_sBIT) is non-zero. }
    sig_bit: png_color_8;  { significant bits in color channels }

    { The tRNS chunk supplies transparency data for paletted images and
      other image types that don't need a full alpha channel.  There are
      "num_trans" transparency values for a paletted image, stored in the
      same order as the palette colors, starting from index 0.  Values
      for the data are in the range [0, 255], ranging from fully transparent
      to fully opaque, respectively.  For non-paletted images, there is a
      single color specified that should be treated as fully transparent.
      Data is valid if (valid & PNG_INFO_tRNS) is non-zero. }
    trans: png_bytep;  { transparent values for paletted image }
    trans_values: png_color_16;  { transparent color for non-palette image }

    { The bKGD chunk gives the suggested image background color if the
      display program does not have its own background color and the image
      is needs to composited onto a background before display.  The colors
      in "background" are normally in the same color space/depth as the
      pixel data.  Data is valid if (valid & PNG_INFO_bKGD) is non-zero. }
    background: png_color_16;

    { The oFFs chunk gives the offset in "offset_unit_type" units rightwards
      and downwards from the top-left corner of the display, page, or other
      application-specific co-ordinate space.  See the PNG_OFFSET_ defines
      below for the unit types.  Valid if (valid & PNG_INFO_oFFs) non-zero. }
    x_offset: png_int_32;  { x offset on page }
    y_offset: png_int_32;  { y offset on page }
    offset_unit_type: png_byte;  { offset units type }

    { The pHYs chunk gives the physical pixel density of the image for
      display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
      defines below).  Data is valid if (valid & PNG_INFO_pHYs) is non-zero. }
    x_pixels_per_unit: png_uint_32;  { horizontal pixel density }
    y_pixels_per_unit: png_uint_32;  { vertical pixel density }
    phys_unit_type: png_byte;  { resolution type (see PNG_RESOLUTION_ below) }

    { The hIST chunk contains the relative frequency or importance of the
      various palette entries, so that a viewer can intelligently select a
      reduced-color palette, if required.  Data is an array of "num_palette"
      values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
      is non-zero. }
    hist: png_uint_16p;

    { The cHRM chunk describes the CIE color characteristics of the monitor
      on which the PNG was created.  This data allows the viewer to do gamut
      mapping of the input image to ensure that the viewer sees the same
      colors in the image as the creator.  Values are in the range
      [0.0, 0.8].  Data valid if (valid & PNG_INFO_cHRM) non-zero. }
    x_white: single;
    y_white: single;
    x_red: single;
    y_red: single;
    x_green: single;
    y_green: single;
    x_blue: single;
    y_blue: single;

    { The pCAL chunk describes a transformation between the stored pixel
      values and original physical data values used to create the image.
      The integer range [0, 2^bit_depth - 1] maps to the floating-point
      range given by [pcal_X0, pcal_X1], and are further transformed by a
      (possibly non-linear) transformation function given by "pcal_type"
      and "pcal_params" into "pcal_units".  Please see the PNG_EQUATION_
      defines below, and the PNG-Group's PNG extensions document for a
      complete description of the transformations and how they should be
      implemented, and for a description of the ASCII parameter strings.
      Data values are valid if (valid & PNG_INFO_pCAL) non-zero. }
    pcal_purpose: png_charp;  { pCAL chunk description string }
    pcal_X0: png_int_32;      { minimum value }
    pcal_X1: png_int_32;      { maximum value }
    pcal_units: png_charp;    { Latin-1 string giving physical units }
    pcal_params: png_charpp;  { ASCII strings containing parameter values }
    pcal_type: png_byte;      { equation type (see PNG_EQUATION_ below) }
    pcal_nparams: png_byte;   { number of parameters given in pcal_params }

{ New members added in libpng-1.0.6 }
    free_me: png_uint_32;     { flags items libpng is responsible for freeing }

    { storage for unknown chunks that the library doesn't recognize. }
    unknown_chunks: png_unknown_chunkp;
    unknown_chunks_num: png_size_t;

    { iCCP chunk data. }
    iccp_name: png_charp;     { profile name }
    iccp_profile: png_charp;  { International Color Consortium profile data }
                            { Note to maintainer: should be png_bytep }
    iccp_proflen: png_uint_32;  { ICC profile data length }
    iccp_compression: png_byte; { Always zero }

    { data on sPLT chunks (there may be more than one). }
    splt_palettes: png_sPLT_tp;
    splt_palettes_num: png_uint_32;

    { The sCAL chunk describes the actual physical dimensions of the
      subject matter of the graphic.  The chunk contains a unit specification
      a byte value, and two ASCII strings representing floating-point
      values.  The values are width and height corresponsing to one pixel
      in the image.  This external representation is converted to double
      here.  Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. }
    scal_unit: png_byte;         { unit of physical scale }

    scal_pixel_width: double;    { width of one pixel }
    scal_pixel_height: double;   { height of one pixel }

    scal_s_width: png_charp;     { string containing height }
    scal_s_height: png_charp;    { string containing width }

    { Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero }
    { Data valid if (valid & PNG_INFO_IDAT) non-zero }
    row_pointers: png_bytepp;        { the image bits }

    int_gamma: png_fixed_point;  { gamma of image, if (valid & PNG_INFO_gAMA) }

    int_x_white: png_fixed_point;
    int_y_white: png_fixed_point;
    int_x_red: png_fixed_point;
    int_y_red: png_fixed_point;
    int_x_green: png_fixed_point;
    int_y_green: png_fixed_point;
    int_x_blue: png_fixed_point;
    int_y_blue: png_fixed_point;
  end;
  png_infop = ^png_info;
  png_infopp = ^png_infop;

const
{ These describe the color_type field in png_info. }
  { color type masks }
  PNG_COLOR_MASK_PALETTE    = 1;
  PNG_COLOR_MASK_COLOR      = 2;
  PNG_COLOR_MASK_ALPHA      = 4;

  { color types.  Note that not all combinations are legal }
  PNG_COLOR_TYPE_GRAY       = 0;
  PNG_COLOR_TYPE_PALETTE    = PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_PALETTE;
  PNG_COLOR_TYPE_RGB        = PNG_COLOR_MASK_COLOR;
  PNG_COLOR_TYPE_RGB_ALPHA  = PNG_COLOR_MASK_COLOR or PNG_COLOR_MASK_ALPHA;
  PNG_COLOR_TYPE_GRAY_ALPHA = PNG_COLOR_MASK_ALPHA;
  { aliases }
  PNG_COLOR_TYPE_RGBA       = PNG_COLOR_TYPE_RGB_ALPHA;
  PNG_COLOR_TYPE_GA         = PNG_COLOR_TYPE_GRAY_ALPHA;

  { This is for compression type. PNG 1.0-1.2 only define the single type. }
  PNG_COMPRESSION_TYPE_BASE     = 0;  { Deflate method 8, 32K window }
  PNG_COMPRESSION_TYPE_DEFAULT  = PNG_COMPRESSION_TYPE_BASE;

  { This is for filter type. PNG 1.0-1.2 only define the single type. }
  PNG_FILTER_TYPE_BASE        =  0;  { Single row per-byte filtering }
  PNG_INTRAPIXEL_DIFFERENCING = 64;  { Used only in MNG datastreams }
  PNG_FILTER_TYPE_DEFAULT     = PNG_FILTER_TYPE_BASE;

  { These are for the interlacing type.  These values should NOT be changed. }
  PNG_INTERLACE_NONE        = 0;  { Non-interlaced image }
  PNG_INTERLACE_ADAM7       = 1;  { Adam7 interlacing }
  PNG_INTERLACE_LAST        = 2;  { Not a valid value }

  { These are for the oFFs chunk.  These values should NOT be changed. }
  PNG_OFFSET_PIXEL          = 0;  { Offset in pixels }
  PNG_OFFSET_MICROMETER     = 1;  { Offset in micrometers (1/10^6 meter) }
  PNG_OFFSET_LAST           = 2;  { Not a valid value }

  { These are for the pCAL chunk.  These values should NOT be changed. }
  PNG_EQUATION_LINEAR       = 0;  { Linear transformation }
  PNG_EQUATION_BASE_E       = 1;  { Exponential base e transform }
  PNG_EQUATION_ARBITRARY    = 2;  { Arbitrary base exponential transform }
  PNG_EQUATION_HYPERBOLIC   = 3;  { Hyperbolic sine transformation }
  PNG_EQUATION_LAST         = 4;  { Not a valid value }

  { These are for the sCAL chunk.  These values should NOT be changed. }
  PNG_SCALE_UNKNOWN         = 0;  { unknown unit (image scale) }
  PNG_SCALE_METER           = 1;  { meters per pixel }
  PNG_SCALE_RADIAN          = 2;  { radians per pixel }
  PNG_SCALE_LAST            = 3;  { Not a valid value }

  { These are for the pHYs chunk.  These values should NOT be changed. }
  PNG_RESOLUTION_UNKNOWN    = 0;  { pixels/unknown unit (aspect ratio) }
  PNG_RESOLUTION_METER      = 1;  { pixels/meter }
  PNG_RESOLUTION_LAST       = 2;  { Not a valid value }

  { These are for the sRGB chunk.  These values should NOT be changed. }
  PNG_sRGB_INTENT_PERCEPTUAL = 0;
  PNG_sRGB_INTENT_RELATIVE   = 1;
  PNG_sRGB_INTENT_SATURATION = 2;
  PNG_sRGB_INTENT_ABSOLUTE   = 3;
  PNG_sRGB_INTENT_LAST       = 4;  { Not a valid value }

  { This is for text chunks }
  PNG_KEYWORD_MAX_LENGTH     = 79;

  { Maximum number of entries in PLTE/sPLT/tRNS arrays }
  PNG_MAX_PALETTE_LENGTH     = 256;

  { These determine if an ancillary chunk's data has been successfully read
    from the PNG header, or if the application has filled in the corresponding
    data in the info_struct to be written into the output file.  The values
    of the PNG_INFO_<chunk> defines should NOT be changed. }
  PNG_INFO_gAMA = $0001;
  PNG_INFO_sBIT = $0002;
  PNG_INFO_cHRM = $0004;
  PNG_INFO_PLTE = $0008;
  PNG_INFO_tRNS = $0010;
  PNG_INFO_bKGD = $0020;
  PNG_INFO_hIST = $0040;
  PNG_INFO_pHYs = $0080;
  PNG_INFO_oFFs = $0100;
  PNG_INFO_tIME = $0200;
  PNG_INFO_pCAL = $0400;
  PNG_INFO_sRGB = $0800;  { GR-P, 0.96a }
  PNG_INFO_iCCP = $1000;  { ESR, 1.0.6 }
  PNG_INFO_sPLT = $2000;  { ESR, 1.0.6 }
  PNG_INFO_sCAL = $4000;  { ESR, 1.0.6 }
  PNG_INFO_IDAT = $8000;  { ESR, 1.0.6 }

type
{ This is used for the transformation routines, as some of them
  change these values for the row.  It also should enable using
  the routines for other purposes. }
  png_row_info = record
    width: png_uint_32;  { width of row }
    rowbytes: png_uint_32;  { number of bytes in row }
    color_type: png_byte;  { color type of row }
    bit_depth: png_byte;  { bit depth of row }
    channels: png_byte;  { number of channels (1, 2, 3, or 4) }
    pixel_depth: png_byte;  { bits per pixel (depth * channels) }
  end;
  png_row_infop = ^png_row_info;
  png_row_infopp = ^png_row_infop;


const
{ Transform masks for the high-level interface }
  PNG_TRANSFORM_IDENTITY       = $0000;    { read and write }
  PNG_TRANSFORM_STRIP_16       = $0001;    { read only }
  PNG_TRANSFORM_STRIP_ALPHA    = $0002;    { read only }
  PNG_TRANSFORM_PACKING        = $0004;    { read and write }
  PNG_TRANSFORM_PACKSWAP       = $0008;    { read and write }
  PNG_TRANSFORM_EXPAND         = $0010;    { read only }
  PNG_TRANSFORM_INVERT_MONO    = $0020;    { read and write }
  PNG_TRANSFORM_SHIFT          = $0040;    { read and write }
  PNG_TRANSFORM_BGR            = $0080;    { read and write }
  PNG_TRANSFORM_SWAP_ALPHA     = $0100;    { read and write }
  PNG_TRANSFORM_SWAP_ENDIAN    = $0200;    { read and write }
  PNG_TRANSFORM_INVERT_ALPHA   = $0400;    { read and write }
  PNG_TRANSFORM_STRIP_FILLER   = $0800;    { WRITE only }

{ Flags for MNG supported features }
  PNG_FLAG_MNG_EMPTY_PLTE     = $01;
  PNG_FLAG_MNG_FILTER_64      = $04;
  PNG_ALL_MNG_FEATURES        = $05;


type
{ These are the function types for the I/O functions and for the functions
  that allow the user to override the default I/O functions with his or her
  own.  The png_error_ptr type should match that of user-supplied warning
  and error functions, while the png_rw_ptr type should match that of the
  user read/write data functions. }

  png_structp = ^png_struct;

  png_error_ptr = procedure(p1: png_structp; p2: png_const_charp); cdecl;
  png_rw_ptr = procedure(p1: png_structp; p2: png_bytep; p3: cardinal); cdecl;
  png_flush_ptr = procedure(p1: png_structp); cdecl;
  png_read_status_ptr = procedure(p1: png_structp; p2: png_uint_32; p3: integer); cdecl;
  png_write_status_ptr = procedure(p1: png_structp; p2: png_uint_32; p3: integer); cdecl;

  png_progressive_info_ptr = procedure(p1: png_structp; p2: png_infop); cdecl;
  png_progressive_end_ptr = procedure(p1: png_structp; p2: png_infop); cdecl;
  png_progressive_row_ptr = procedure(p1: png_structp; p2: png_bytep; p3: png_uint_32; p4: integer); cdecl;

  png_user_transform_ptr = procedure(p1: png_structp; p2: png_row_infop; p3: png_bytep); cdecl;
  png_user_chunk_ptr = function(p1: png_structp; p2: png_unknown_chunkp): integer; cdecl;
  png_unknown_chunk_ptr = procedure(p1: png_structp); cdecl;

  png_malloc_ptr = function(p1: png_structp; p2: png_size_t): png_voidp; cdecl;
  png_free_ptr = procedure(p1: png_structp; p2: png_voidp); cdecl;

{ The structure that holds the information to read and write PNG files.
  The only people who need to care about what is inside of this are the
  people who will be modifying the library for their own special needs.
  It should NOT be accessed directly by an application, except to store
  the jmp_buf. }
  
  png_struct = record
    jmp_buf: array[0..15] of Integer; { used in png_error }

    error_fn: png_error_ptr;    { function for printing errors and aborting }
    warning_fn: png_error_ptr;  { function for printing warnings }
    error_ptr: png_voidp;       { user supplied struct for error functions }
    write_data_fn: png_rw_ptr;  { function for writing output data }
    read_data_fn: png_rw_ptr;   { function for reading input data }
    io_ptr: png_voidp;          { ptr to application struct for I/O functions }

    read_user_transform_fn: png_user_transform_ptr; { user read transform }

    write_user_transform_fn: png_user_transform_ptr; { user write transform }

{ These were added in libpng-1.0.2 }
    user_transform_ptr: png_voidp; { user supplied struct for user transform }
    user_transform_depth: png_byte;    { bit depth of user transformed pixels }
    user_transform_channels: png_byte; { channels in user transformed pixels }

    mode: png_uint_32;          { tells us where we are in the PNG file }
    flags: png_uint_32;         { flags indicating various things to libpng }
    transformations: png_uint_32; { which transformations to perform }

    zstream: pointer;           { pointer to decompression structure (below) }
    zbuf: png_bytep;            { buffer for zlib }
    zbuf_size: png_size_t;      { size of zbuf }
    zlib_level: Integer;        { holds zlib compression level }
    zlib_method: Integer;       { holds zlib compression method }
    zlib_window_bits: Integer;  { holds zlib compression window bits }
    zlib_mem_level: Integer;    { holds zlib compression memory level }
    zlib_strategy: Integer;     { holds zlib compression strategy }

    width: png_uint_32;         { width of image in pixels }
    height: png_uint_32;        { height of image in pixels }
    num_rows: png_uint_32;      { number of rows in current pass }
    usr_width: png_uint_32;     { width of row at start of write }
    rowbytes: png_uint_32;      { size of row in bytes }
    irowbytes: png_uint_32;     { size of current interlaced row in bytes }
    iwidth: png_uint_32;        { width of current interlaced row in pixels }
    row_number: png_uint_32;    { current row in interlace pass }
    prev_row: png_bytep;        { buffer to save previous (unfiltered) row }
    row_buf: png_bytep;         { buffer to save current (unfiltered) row }
    sub_row: png_bytep;         { buffer to save "sub" row when filtering }
    up_row: png_bytep;          { buffer to save "up" row when filtering }
    avg_row: png_bytep;         { buffer to save "avg" row when filtering }
    paeth_row: png_bytep;       { buffer to save "Paeth" row when filtering }
    row_info: png_row_info;     { used for transformation routines }
  
    idat_size: png_uint_32;     { current IDAT size for read }
    crc: png_uint_32;           { current chunk CRC value }
    palette: png_colorp;        { palette from the input file }
    num_palette: png_uint_16;   { number of color entries in palette }
    num_trans: png_uint_16;     { number of transparency values }
    chunk_name: array[0..4] of png_byte; { null-terminated name of current chunk }
    compression: png_byte;      { file compression type (always 0) }
    filter: png_byte;           { file filter type (always 0) }
    interlaced: png_byte;       { PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 }
    pass: png_byte;             { current interlace pass (0 - 6) }
    do_filter: png_byte;        { row filter flags (see PNG_FILTER_ below ) }
    color_type: png_byte;       { color type of file }
    bit_depth: png_byte;        { bit depth of file }
    usr_bit_depth: png_byte;    { bit depth of users row }
    pixel_depth: png_byte;      { number of bits per pixel }
    channels: png_byte;         { number of channels in file }
    usr_channels: png_byte;     { channels at start of write }
    sig_bytes: png_byte;        { magic bytes read/written from start of file }

    filler: png_byte;           { filler byte for pixel expansion }

    background_gamma_type: png_byte;
    background_gamma: single;
    background: png_color_16;   { background color in screen gamma space }
    background_1: png_color_16; { background normalized to gamma 1.0 }

    output_flush_fn: png_flush_ptr;  { Function for flushing output }
    flush_dist: png_uint_32;    { how many rows apart to flush, 0 - no flush }
    flush_rows: png_uint_32;    { number of rows written since last flush }

    gamma_shift: integer;       { number of "insignificant" bits 16-bit gamma }
    gamma: single;              { file gamma value }
    screen_gamma: single;       { screen gamma value (display_exponent) }

    gamma_table: png_bytep;     { gamma table for 8-bit depth files }
    gamma_from_1: png_bytep;    { converts from 1.0 to screen }
    gamma_to_1: png_bytep;      { converts from file to 1.0 }
    gamma_16_table: png_uint_16pp;  { gamma table for 16-bit depth files }
    gamma_16_from_1: png_uint_16pp;  { converts from 1.0 to screen }
    gamma_16_to_1: png_uint_16pp;  { converts from file to 1.0 }

    sig_bit: png_color_8;       { significant bits in each available channel }

    shift: png_color_8;         { shift for significant bit tranformation }

    trans: png_bytep;           { transparency values for paletted files }
    trans_values: png_color_16; { transparency values for non-paletted files }

    read_row_fn: png_read_status_ptr;   { called after each row is decoded }
    write_row_fn: png_write_status_ptr; { called after each row is encoded }

    info_fn: png_progressive_info_ptr; { called after header data fully read }
    row_fn: png_progressive_row_ptr;   { called after each prog. row is decoded }
    end_fn: png_progressive_end_ptr;   { called after image is complete }
    save_buffer_ptr: png_bytep;        { current location in save_buffer }
    save_buffer: png_bytep;            { buffer for previously read data }
    current_buffer_ptr: png_bytep;     { current location in current_buffer }
    current_buffer: png_bytep;         { buffer for recently used data }
    push_length: png_uint_32;          { size of current input chunk }
    skip_length: png_uint_32;          { bytes to skip in input data }
    save_buffer_size: png_size_t;      { amount of data now in save_buffer }
    save_buffer_max: png_size_t;       { total size of save_buffer }
    buffer_size: png_size_t;           { total amount of available input data }
    current_buffer_size: png_size_t;   { amount of data now in current_buffer }
    process_mode: integer;             { what push library is currently doing }
    cur_palette: integer;              { current push library palette index }

    current_text_size: png_size_t;     { current size of text input data }
    current_text_left: png_size_t;     { how much text left to read in input }
    current_text: png_charp;           { current text chunk buffer }
    current_text_ptr: png_charp;       { current location in current_text }

    { for the Borland special 64K segment handler }
    offset_table_ptr: png_bytepp;
    offset_table: png_bytep;
    offset_table_number: png_uint_16;
    offset_table_count: png_uint_16;
    offset_table_count_free: png_uint_16;

    palette_lookup: png_bytep;         { lookup table for dithering }
    dither_index: png_bytep;           { index translation for palette files }

    hist: png_uint_16p;                { histogram }

    heuristic_method: png_byte;        { heuristic for row filter selection }
    num_prev_filters: png_byte;        { number of weights for previous rows }
    prev_filters: png_bytep;           { filter type(s) of previous row(s) }
    filter_weights: png_uint_16p;      { weight(s) for previous line(s) }
    inv_filter_weights: png_uint_16p;  { 1/weight(s) for previous line(s) }
    filter_costs: png_uint_16p;        { relative filter calculation cost }
    inv_filter_costs: png_uint_16p;    { 1/relative filter calculation cost }

    time_buffer: png_charp;            { String to hold RFC 1123 time text }

    { New members added in libpng-1.0.6 }

    free_me: png_uint_32;       { flags items libpng is responsible for freeing }

    user_chunk_ptr: png_voidp;
    read_user_chunk_fn: png_user_chunk_ptr;  { user read chunk handler }

    num_chunk_list: integer;
    chunk_list: png_bytep;

    { New members added in libpng-1.0.3 }
    rgb_to_gray_status: png_byte;

    { These were changed from png_byte in libpng-1.0.6 }
    rgb_to_gray_red_coeff: png_uint_16;
    rgb_to_gray_green_coeff: png_uint_16;
    rgb_to_gray_blue_coeff: png_uint_16;
    
    { New member added in libpng-1.0.4 (renamed in 1.0.9) }
    { changed from png_byte to png_uint_32 at version 1.2.0 }
    mng_features_permitted: png_uint_32;

    { New member added in libpng-1.0.7 }
    int_gamma: png_fixed_point;

    { New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 }
    filter_type: png_byte;

    { New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 }
    row_buf_size: png_uint_32;

    { New members added in libpng-1.2.0 }

    mmx_bitdepth_threshold: png_byte;
    mmx_rowbytes_threshold: png_uint_32;
    asm_flags: png_uint_32;

    { New members added in libpng-1.0.2 but first enabled by default in 1.2.0 }
    mem_ptr: png_voidp;                { user supplied struct for mem functions }
    malloc_fn: png_malloc_ptr;         { function for allocating memory }
    free_fn: png_free_ptr;             { function for freeing memory }

    { New member added in libpng-1.0.13 and 1.2.0 }
    big_row_buf: png_bytep;            { buffer to save current (unfiltered) row }

    { The following three members were added at version 1.0.14 and 1.2.4 }
    dither_sort: png_bytep;            { working sort array }
    index_to_palette: png_bytep;       { where the original index currently is }
                                       { in the palette }
    palette_to_index: png_bytep;       { which original index points to this }
                                       { palette color }

    { New members added in libpng-1.0.16 and 1.2.6 }
    compression_type: png_byte;

    user_width_max: png_uint_32;
    user_height_max: png_uint_32;
  end;
  png_structpp = ^png_structp;

  procedure pngReadFn(png_ptr: png_structp; Data: png_bytep; length: png_size_t);
    cdecl;
  procedure pngWriteFn(png_ptr: png_structp; Data: png_bytep; length: png_size_t);
    cdecl;
  procedure pngErrorFn(struct: png_structp; str: png_const_charp);
    cdecl;
  procedure pngWarnFn(struct: png_structp; str: png_const_charp);
    cdecl;

var
{ Here are the function definitions most commonly used.  This is not
  the place to find out how to use libpng.  See libpng.txt for the
  full explanation, see example.c for the summary.  This just provides
  a simple one line description of the use of each function. }

{ Returns the version number of the library }
  png_access_version_number: function: png_uint_32; cdecl;

{ Tell lib we have already handled the first <num_bytes> magic bytes.
  Handling more than 8 bytes from the beginning of the file is an error.}
  png_set_sig_bytes: procedure(png_ptr: png_structp; num_bytes: integer); cdecl;
  
{ Check sig[start] through sig[start + num_to_check - 1] to see if it's a
  PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
  signature, and non-zero otherwise.  Having num_to_check == 0 or
  start > 7 will always fail (ie return non-zero). }
  png_sig_cmp: function(sig: png_bytep; start: png_size_t; num_to_check: png_size_t): integer; cdecl;
  
{ Simple signature checking function.  This is the same as calling
  png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). }
  png_check_sig: function(sig: png_bytep; num: integer): integer; cdecl;
  
{ Allocate and initialize png_ptr struct for reading, and any other memory. }
  png_create_read_struct: function(user_png_ver: png_const_charp; error_ptr: png_voidp; error_fn: png_error_ptr; warn_fn: png_error_ptr): png_structp; cdecl;

{ Allocate and initialize png_ptr struct for writing, and any other memory }
  png_create_write_struct: function(user_png_ver: png_const_charp; error_ptr: png_voidp; error_fn: png_error_ptr; warn_fn: png_error_ptr): png_structp; cdecl;

  png_get_compression_buffer_size: function(png_ptr: png_structp): png_uint_32; cdecl;
  png_set_compression_buffer_size: procedure(png_ptr: png_structp; size: png_uint_32); cdecl;

{ Reset the compression stream }
  png_reset_zstream: function(png_ptr: png_structp): integer; cdecl;

{ New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) }
  png_create_read_struct_2: function(user_png_ver: png_const_charp; error_ptr: png_voidp; error_fn: png_error_ptr; warn_fn: png_error_ptr; mem_ptr: png_voidp; malloc_fn: png_malloc_ptr; free_fn: png_free_ptr): png_structp; cdecl;
  png_create_write_struct_2: function(user_png_ver: png_const_charp; error_ptr: png_voidp; error_fn: png_error_ptr; warn_fn: png_error_ptr; mem_ptr: png_voidp; malloc_fn: png_malloc_ptr; free_fn: png_free_ptr): png_structp; cdecl;

{ Write a PNG chunk - size, type, (optional) data, CRC. }
  png_write_chunk: procedure (png_ptr: png_structp; chunk_name: png_bytep; data: png_bytep; length: png_size_t); cdecl;

{ Write the start of a PNG chunk - length and chunk name. }
  png_write_chunk_start: procedure(png_ptr: png_structp; chunk_name: png_bytep; length: png_uint_32); cdecl;

{ Write the data of a PNG chunk started with png_write_chunk_start(). }
  png_write_chunk_data: procedure(png_ptr: png_structp; data: png_bytep; length: png_size_t); cdecl;

{ Finish a chunk started with png_write_chunk_start() (includes CRC). }
  png_write_chunk_end: procedure(png_ptr: png_structp); cdecl;

{ Allocate and initialize the info structure }
  png_create_info_struct: function(png_ptr: png_structp): png_infop; cdecl;

{ Initialize the info structure (old interface - DEPRECATED) }
  png_info_init: procedure(info_ptr: png_infop); cdecl;

  png_info_init_3: procedure(info_ptr: png_infopp; png_info_struct_size: png_size_t); cdecl;

{ Writes all the PNG information before the image. }
  png_write_info_before_PLTE: procedure(png_ptr: png_structp; info_ptr: png_infop); cdecl;
  png_write_info: procedure(png_ptr: png_structp; info_ptr: png_infop); cdecl;

{ read the information before the actual image data. }
  png_read_info: procedure(png_ptr: png_structp; info_ptr: png_infop); cdecl;

  png_convert_to_rfc1123: function(png_ptr: png_structp; ptime: png_timep): png_charp; cdecl;
  
{ "time.h" functions are not supported on WindowsCE }
{ convert from a struct tm to png_time }
  png_convert_from_struct_tm: procedure(ptime: png_timep; ttime: TMp); cdecl;

{ convert from time_t to png_time.  Uses gmtime() }
  png_convert_from_time_t: procedure(ptime: png_timep; ttime: time_t);

{ Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. }
  png_set_expand: procedure(png_ptr: png_structp); cdecl;
  png_set_expand_gray_1_2_4_to_8: procedure(png_ptr: png_structp); cdecl;
  png_set_palette_to_rgb: procedure(png_ptr: png_structp); cdecl;
  png_set_tRNS_to_alpha: procedure(png_ptr: png_structp); cdecl;

{ Deprecated }
  png_set_gray_1_2_4_to_8: procedure(png_ptr: png_structp); cdecl;

  
{ Use blue, green, red order for pixels. }
  png_set_bgr: procedure(png_ptr: png_structp); cdecl;

{ Expand the grayscale to 24-bit RGB if necessary. }
  png_set_gray_to_rgb: procedure(png_ptr: png_structp); cdecl;

{ Reduce RGB to grayscale. }
  png_set_rgb_to_gray: procedure(png_ptr: png_structp; error_action: integer; red: double; green: double); cdecl;
  png_set_rgb_to_gray_fixed: procedure(png_ptr: png_structp; error_action: integer; red: png_fixed_point; green: png_fixed_point); cdecl;
  png_get_rgb_to_gray_status: function(png_ptr: png_structp): png_byte; cdecl;

  png_build_grayscale_palette: procedure(bit_depth: integer; palette: png_colorp); cdecl;
  
  png_set_strip_alpha: procedure(png_ptr: png_structp); cdecl;
  png_set_swap_alpha: procedure(png_ptr: png_structp); cdecl;
  png_set_invert_alpha: procedure(png_ptr: png_structp); cdecl;

{ Add a filler byte to 8-bit Gray or 24-bit RGB images. }
  png_set_filler: procedure(png_ptr: png_structp; filler: png_uint_32; flags: integer); cdecl;

const
  { The values of the PNG_FILLER_ defines should NOT be changed }
  PNG_FILLER_BEFORE = 0;
  PNG_FILLER_AFTER  = 1;

var
{ Add an alpha byte to 8-bit Gray or 24-bit RGB images. }
  png_set_add_alpha: procedure(png_ptr: png_structp; filler: png_uint_32; flags: integer); cdecl;

{ Swap bytes in 16-bit depth files. }
  png_set_swap: procedure(png_ptr: png_structp); cdecl;

{ Use 1 byte per pixel in 1, 2, or 4-bit depth files. }
  png_set_packing: procedure(png_ptr: png_structp); cdecl;

{ Swap packing order of pixels in bytes. }
  png_set_packswap: procedure(png_ptr: png_structp); cdecl;

{ Converts files to legal bit depths. }
  png_set_shift: procedure(png_ptr: png_structp; true_bits: png_color_8p); cdecl;

{ Have the code handle the interlacing.  Returns the number of passes. }
  png_set_interlace_handling: function(png_ptr: png_structp): integer;

{ Invert monochrome files }
  png_set_invert_mono: procedure(png_ptr: png_structp); cdecl;

{ Handle alpha and tRNS by replacing with a background color. }
  png_set_background: procedure(png_ptr: png_structp; background_color: png_color_16p; background_gamma_code: integer; need_expand: integer; background_gamma: double); cdecl;

const
  PNG_BACKGROUND_GAMMA_UNKNOWN = 0;
  PNG_BACKGROUND_GAMMA_SCREEN  = 1;
  PNG_BACKGROUND_GAMMA_FILE    = 2;
  PNG_BACKGROUND_GAMMA_UNIQUE  = 3;

var
{ strip the second byte of information from a 16-bit depth file. }
  png_set_strip_16: procedure(png_ptr: png_structp); cdecl;

{ Turn on dithering, and reduce the palette to the number of colors available. }
  png_set_dither: procedure(png_ptr: png_structp; palette: png_colorp; num_palette: integer; maximum_colors: integer; histogram: png_uint_16p; full_dither: integer); cdecl;

{ Handle gamma correction. Screen_gamma=(display_exponent) }
  png_set_gamma: procedure(png_ptr: png_structp; screen_gamma: double; default_file_gamma: double); cdecl;

{ Permit or disallow empty PLTE (0: not permitted, 1: permitted) }
{ Deprecated and will be removed.  Use png_permit_mng_features() instead. }
  png_permit_empty_plte: procedure(png_ptr: png_structp; empty_plte_permitted: integer); cdecl;

{ Set how many lines between output flushes - 0 for no flushing }
  png_set_flush: procedure(png_ptr: png_structp; nrows: integer); cdecl;
  
{ Flush the current PNG output buffer }
  png_write_flush: procedure(png_ptr: png_structp); cdecl;

{ optional update palette with requested transformations }
  png_start_read_image: procedure(png_ptr: png_structp); cdecl;

{ optional call to update the users info structure }
  png_read_update_info: procedure(png_ptr: png_structp; info_ptr: png_infop); cdecl;

{ read one or more rows of image data. }
  png_read_rows: procedure(png_ptr: png_structp; row: png_bytepp; display_row: png_bytepp; num_rows: png_uint_32); cdecl;

{ read a row of data. }
  png_read_row: procedure(png_ptr: png_structp; row: png_bytep; display_row: png_bytep); cdecl;

{ read the whole image into memory at once. }
  png_read_image: procedure(png_ptr: png_structp; image: png_bytepp); cdecl;

{ write a row of image data }
  png_write_row: procedure(png_ptr: png_structp; row: png_bytep); cdecl;

{ write a few rows of image data }
  png_write_rows: procedure(png_ptr: png_structp; row: png_bytepp; num_rows: png_uint_32); cdecl;

{ write the image data }
  png_write_image: procedure(png_ptr: png_structp; image: png_bytepp); cdecl;

{ writes the end of the PNG file. }
  png_write_end: procedure(png_ptr: png_structp; info_ptr: png_infop); cdecl;

{ read the end of the PNG file. }
  png_read_end: procedure(png_ptr: png_structp; info_ptr: png_infop); cdecl;

{ free any memory associated with the png_info_struct }
  png_destroy_info_struct: procedure(png_ptr: png_structp; info_ptr_ptr: png_infopp); cdecl;

{ free any memory associated with the png_struct and the png_info_structs }
  png_destroy_read_struct: procedure(png_ptr_ptr: png_structpp; info_ptr_ptr: png_infopp; end_info_ptr_ptr: png_infopp); cdecl;

{ free any memory associated with the png_struct and the png_info_structs }
  png_destroy_write_struct: procedure(png_ptr_ptr: png_structpp; info_ptr_ptr: png_infopp); cdecl;

{ set the libpng method of handling chunk CRC errors }
  png_set_crc_action: procedure (png_ptr: png_structp; crit_action: integer; ancil_action: integer);
  
const
{ Values for png_set_crc_action() to say how to handle CRC errors in
  ancillary and critical chunks, and whether to use the data contained
  therein.  Note that it is impossible to "discard" data in a critical
  chunk.  For versions prior to 0.90, the action was always error/quit,
  whereas in version 0.90 and later, the action for CRC errors in ancillary
  chunks is warn/discard.  These values should NOT be changed.
 
  value                        action:critical     action:ancillary  }
 
  PNG_CRC_DEFAULT      = 0;  { error/quit          warn/discard data }
  PNG_CRC_ERROR_QUIT   = 1;  { error/quit          error/quit        }
  PNG_CRC_WARN_DISCARD = 2;  { (INVALID)           warn/discard data }
  PNG_CRC_WARN_USE     = 3;  { warn/use data       warn/use data     }
  PNG_CRC_QUIET_USE    = 4;  { quiet/use data      quiet/use data    }
  PNG_CRC_NO_CHANGE    = 5;  { use current value   use current value }

{ These functions give the user control over the scan-line filtering in
  libpng and the compression methods used by zlib.  These functions are
  mainly useful for testing, as the defaults should work with most users.
  Those users who are tight on memory or want faster performance at the
  expense of compression can modify them.  See the compression library
  header file (zlib.h) for an explination of the compression functions. }

var
{ set the filtering method(s) used by libpng.  Currently, the only valid
  value for "method" is 0.}
  png_set_filter: procedure(png_ptr: png_structp; method: integer; filters: integer); cdecl;

const
{ Flags for png_set_filter() to say which filters to use.  The flags
  are chosen so that they don't conflict with real filter types
  below, in case they are supplied instead of the #defined constants.
  These values should NOT be changed. }
  PNG_NO_FILTERS     = $00;
  PNG_FILTER_NONE    = $08;
  PNG_FILTER_SUB     = $10;
  PNG_FILTER_UP      = $20;
  PNG_FILTER_AVG     = $40;
  PNG_FILTER_PAETH   = $80;
  PNG_ALL_FILTERS    = PNG_FILTER_NONE or PNG_FILTER_SUB or PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH;

{ Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
  These defines should NOT be changed. }
  PNG_FILTER_VALUE_NONE  = 0;
  PNG_FILTER_VALUE_SUB   = 1;
  PNG_FILTER_VALUE_UP    = 2;
  PNG_FILTER_VALUE_AVG   = 3;
  PNG_FILTER_VALUE_PAETH = 4;
  PNG_FILTER_VALUE_LAST  = 5;
  
var
{ EXPERIMENTAL }
{ The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
  defines, either the default (minimum-sum-of-absolute-differences), or
  the experimental method (weighted-minimum-sum-of-absolute-differences).

  Weights are factors >= 1.0, indicating how important it is to keep the
  filter type consistent between rows.  Larger numbers mean the current
  filter is that many times as likely to be the same as the "num_weights"
  previous filters.  This is cumulative for each previous row with a weight.
  There needs to be "num_weights" values in "filter_weights", or it can be
  NULL if the weights aren't being specified.  Weights have no influence on
  the selection of the first row filter.  Well chosen weights can (in theory)
  improve the compression for a given image.

  Costs are factors >= 1.0 indicating the relative decoding costs of a
  filter type.  Higher costs indicate more decoding expense, and are
  therefore less likely to be selected over a filter with lower computational
  costs.  There needs to be a value in "filter_costs" for each valid filter
  type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
  setting the costs.  Costs try to improve the speed of decompression without
  unduly increasing the compressed image size.

  A negative weight or cost indicates the default value is to be used, and
  values in the range [0.0, 1.0) indicate the value is to remain unchanged.
  The default values for both weights and costs are currently 1.0, but may
  change if good general weighting/cost heuristics can be found.  If both
  the weights and costs are set to 1.0, this degenerates the WEIGHTED method
  to the UNWEIGHTED method, but with added encoding time/computation. }
  png_set_filter_heuristics: procedure(png_ptr: png_structp; heuristic_method: integer; num_weights: integer; filter_weights: png_doublep; filter_costs: png_doublep); cdecl;

const
{ Heuristic used for row filter selection.  These defines should NOT be
  changed. }
  PNG_FILTER_HEURISTIC_DEFAULT    = 0;  { Currently "UNWEIGHTED" }
  PNG_FILTER_HEURISTIC_UNWEIGHTED = 1;  { Used by libpng < 0.95 }
  PNG_FILTER_HEURISTIC_WEIGHTED   = 2;  { Experimental feature }
  PNG_FILTER_HEURISTIC_LAST       = 3;  { Not a valid value }

var
{ Set the library compression level.  Currently, valid values range from
  0 - 9, corresponding directly to the zlib compression levels 0 - 9
  (0 - no compression, 9 - "maximal" compression).  Note that tests have
  shown that zlib compression levels 3-6 usually perform as well as level 9
  for PNG images, and do considerably fewer caclulations.  In the future,
  these values may not correspond directly to the zlib compression levels. }
  png_set_compression_level: procedure(png_ptr: png_structp; level: integer); cdecl;
  png_set_compression_mem_level: procedure(png_ptr: png_structp; mem_level: integer); cdecl;
  png_set_compression_strategy: procedure(png_ptr: png_structp; strategy: integer); cdecl;
  png_set_compression_window_bits: procedure(png_ptr: png_structp; window_bits: integer); cdecl;
  png_set_compression_method: procedure(png_ptr: png_structp; method: integer); cdecl;

{ These next functions are called for input/output, memory, and error
  handling.  They are in the file pngrio.c, pngwio.c, and pngerror.c,
  and call standard C I/O routines such as fread(), fwrite(), and
  fprintf().  These functions can be made to use other I/O routines
  at run time for those applications that need to handle I/O in a
  different manner by calling png_set_???_fn().  See libpng.txt for
  more information. }
 
{ Initialize the input/output for the PNG file to the default functions. }
  png_init_io: procedure(png_ptr: png_structp; fp: png_FILE_p);
  
{ Replace the (error and abort), and warning functions with user
  supplied functions.  If no messages are to be printed you must still
  write and use replacement functions. The replacement error_fn should
  still do a longjmp to the last setjmp location if you are using this
  method of error handling.  If error_fn or warning_fn is NULL, the
  default function will be used. }
  png_set_error_fn: procedure(png_ptr: png_structp; error_ptr: png_voidp; error_fn: png_error_ptr; warning_fn: png_error_ptr); cdecl;

{ Return the user pointer associated with the error functions }
  png_get_error_ptr: function(png_ptr: png_structp): png_voidp; cdecl;

{ Replace the default data output functions with a user supplied one(s).
  If buffered output is not used, then output_flush_fn can be set to NULL.
  If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
  output_flush_fn will be ignored (and thus can be NULL). }
  png_set_write_fn: procedure(png_ptr: png_structp; io_ptr: png_voidp; write_data_fn: png_rw_ptr; output_flush_fn: png_flush_ptr); cdecl;

{ Replace the default data input function with a user supplied one. }
  png_set_read_fn: procedure(png_ptr: png_structp; io_ptr: png_voidp; read_data_fn: png_rw_ptr); cdecl;

{ Return the user pointer associated with the I/O functions }
  png_get_io_ptr: function(png_ptr: png_structp): png_voidp; cdecl;

  png_set_read_status_fn: procedure(png_ptr: png_structp; read_row_fn: png_read_status_ptr); cdecl;
  png_set_write_status_fn: procedure(png_ptr: png_structp; write_row_fn: png_write_status_ptr); cdecl;

{ Replace the default memory allocation functions with user supplied one(s). }
  png_set_mem_fn: procedure(png_ptr: png_structp; mem_ptr: png_voidp; malloc_fn: png_malloc_ptr; free_fn: png_free_ptr); cdecl;
  
{ Return the user pointer associated with the memory functions }
  png_get_mem_ptr: function(png_ptr: png_structp): png_voidp; cdecl;

  png_set_read_user_transform_fn: procedure(png_ptr: png_structp; read_user_transform_fn: png_user_transform_ptr); cdecl;
  png_set_write_user_transform_fn: procedure(png_ptr: png_structp; write_user_transform_fn: png_user_transform_ptr); cdecl;
  png_set_user_transform_info: procedure(png_ptr: png_structp; user_transform_ptr: png_voidp; user_transform_depth: integer; user_transform_channels: integer); cdecl;

{ Return the user pointer associated with the user transform functions }
  png_get_user_transform_ptr: function(png_ptr: png_structp): png_voidp;

  png_set_read_user_chunk_fn: procedure(png_ptr: png_structp; user_chunk_ptr: png_voidp; read_user_chunk_fn: png_user_chunk_ptr); cdecl;
  png_get_user_chunk_ptr: function(png_ptr: png_structp): png_voidp;

{ Sets the function callbacks for the push reader, and a pointer to a
  user-defined structure available to the callback functions. }
  png_set_progressive_read_fn: procedure (png_ptr: png_structp; progressive_ptr: png_voidp; info_fn: png_progressive_info_ptr; row_fn: png_progressive_row_ptr; end_fn: png_progressive_end_ptr); cdecl;

{ returns the user pointer associated with the push read functions }
  png_get_progressive_ptr: function(png_ptr: png_structp): png_voidp; cdecl;

{ function to be called when data becomes available }
  png_process_data: procedure(png_ptr: png_structp; info_ptr: png_infop; buffer: png_bytep; buffer_size: png_size_t); cdecl;

{ function that combines rows.  Not very much different than the
  png_combine_row() call.  Is this even used????? }
  png_progressive_combine_row: procedure(png_ptr: png_structp; old_row: png_bytep; new_row: png_bytep); cdecl;

  png_malloc: function(png_ptr: png_structp; size: png_uint_32): png_voidp; cdecl;

{ Added at libpng version 1.2.4 }
  png_malloc_warn: function(png_ptr: png_structp; size: png_uint_32): png_voidp;

{ frees a pointer allocated by png_malloc() }
  png_free: procedure(png_ptr: png_structp; ptr: png_voidp); cdecl;

{ Function to allocate memory for zlib. }
  png_zalloc: function(png_ptr: pointer; items: cardinal; size: cardinal): pointer; cdecl;

{ Function to free memory for zlib }
  png_zfree: procedure(png_ptr: pointer; ptr: pointer); cdecl;

{ Free data that was allocated internally }
  png_free_data: procedure(png_ptr: png_structp; info_ptr: png_infop; free_me: png_uint_32; num: integer); cdecl;

{ Reassign responsibility for freeing existing data, whether allocated
  by libpng or by the application }
  png_data_freer: procedure(png_ptr: png_structp; info_ptr: png_infop; freer: integer; mask: png_uint_32); cdecl;

const
{ assignments for png_data_freer }
  PNG_DESTROY_WILL_FREE_DATA = 1;
  PNG_SET_WILL_FREE_DATA = 1;
  PNG_USER_WILL_FREE_DATA = 2;
{ Flags for png_ptr->free_me and info_ptr->free_me }
  PNG_FREE_HIST = $0008;
  PNG_FREE_ICCP = $0010;
  PNG_FREE_SPLT = $0020;
  PNG_FREE_ROWS = $0040;
  PNG_FREE_PCAL = $0080;
  PNG_FREE_SCAL = $0100;
  PNG_FREE_UNKN = $0200;
  PNG_FREE_LIST = $0400;
  PNG_FREE_PLTE = $1000;
  PNG_FREE_TRNS = $2000;
  PNG_FREE_TEXT = $4000;
  PNG_FREE_ALL  = $7fff;
  PNG_FREE_MUL  = $4220; { PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN }
  
var  
  png_malloc_default: function(png_ptr: png_structp; size: png_uint_32): png_voidp; cdecl;
  png_free_default: procedure(png_ptr: png_structp; ptr: png_voidp); cdecl;

  png_memcpy_check: function(png_ptr: png_structp; s1: png_voidp; s2: png_voidp; size: png_uint_32): png_voidp; cdecl;
  png_memset_check: function(png_ptr: png_structp; s1: png_voidp; value: integer; size: png_uint_32): png_voidp; cdecl;

  png_far_to_near: function(png_ptr: png_structp; ptr: png_voidp; check: integer): pointer; cdecl;

{ Fatal error in PNG image of libpng - can't continue }
  png_error: procedure(png_ptr: png_structp; error_message: png_const_charp); cdecl;

{ The same, but the chunk name is prepended to the error string. }
  png_chunk_error: procedure(png_ptr: png_structp; error_message: png_const_charp); cdecl;

{ Non-fatal error in libpng.  Can continue, but may have a problem. }
  png_warning: procedure(png_ptr: png_structp; warning_message: png_const_charp); cdecl;

{ Non-fatal error in libpng, chunk name is prepended to message. }
  png_chunk_warning: procedure(png_ptr: png_structp; warning_message: png_const_charp); cdecl;

{ The png_set_<chunk> functions are for storing values in the png_info_struct.
  Similarly, the png_get_<chunk> calls are used to read values from the
  png_info_struct, either storing the parameters in the passed variables, or
  setting pointers into the png_info_struct where the data is stored.  The
  png_get_<chunk> functions return a non-zero value if the data was available
  in info_ptr, or return zero and do not change any of the parameters if the
  data was not available.
 
  These functions should be used instead of directly accessing png_info
  to avoid problems with future changes in the size and internal layout of
  png_info_struct. }
  
{ Returns "flag" if chunk data is valid in info_ptr. }
  png_get_valid: function(png_ptr: png_structp; info_ptr: png_infop; flag: png_uint_32): png_uint_32; cdecl;

{ Returns number of bytes needed to hold a transformed row. }
  png_get_rowbytes: function(png_ptr: png_structp; info_ptr: png_infop): png_uint_32; cdecl;

{ Returns row_pointers, which is an array of pointers to scanlines that was
  returned from png_read_png(). }
  png_get_rows: function(png_ptr: png_structp; info_ptr: png_infop): png_bytepp; cdecl;
  
{ Set row_pointers, which is an array of pointers to scanlines for use
  by png_write_png(). }
  png_set_rows: procedure(png_ptr: png_structp; info_ptr: png_infop; row_pointers: png_bytepp); cdecl;

{ Returns number of color channels in image. }
  png_get_channels: function(png_ptr: png_structp; info_ptr: png_infop): png_byte; cdecl;

{ Returns image width in pixels. }
  png_get_image_width: function(png_ptr: png_structp; info_ptr: png_infop): png_uint_32; cdecl;

{ Returns image height in pixels. }
  png_get_image_height: function(png_ptr: png_structp; info_ptr: png_infop): png_uint_32; cdecl;

{ Returns image bit_depth. }
  png_get_bit_depth: function(png_ptr: png_structp; info_ptr: png_infop): png_byte; cdecl;

{ Returns image color_type. }
  png_get_color_type: function(png_ptr: png_structp; info_ptr: png_infop): png_byte; cdecl;

{ Returns image filter_type. }
  png_get_filter_type: function(png_ptr: png_structp; info_ptr: png_infop): png_byte; cdecl;

{ Returns image interlace_type. }
  png_get_interlace_type: function(png_ptr: png_structp; info_ptr: png_infop): png_byte; cdecl;

{ Returns image compression_type. }
  png_get_compression_type: function(png_ptr: png_structp; info_ptr: png_infop): png_byte; cdecl;
  
{ Returns image resolution in pixels per meter, from pHYs chunk data. }
  png_get_pixels_per_meter: function(png_ptr: png_structp; info_ptr: png_infop): png_uint_32; cdecl;
  png_get_x_pixels_per_meter: function(png_ptr: png_structp; info_ptr: png_infop): png_uint_32; cdecl;
  png_get_y_pixels_per_meter: function(png_ptr: png_structp; info_ptr: png_infop): png_uint_32; cdecl;

{ Returns pixel aspect ratio, computed from pHYs chunk data. }
  png_get_pixel_aspect_ratio: function(png_ptr: png_structp; info_ptr: png_infop): single; cdecl;

{ Returns image x, y offset in pixels or microns, from oFFs chunk data. }
  png_get_x_offset_pixels: function(png_ptr: png_structp; info_ptr: png_infop): png_int_32; cdecl;
  png_get_y_offset_pixels: function(png_ptr: png_structp; info_ptr: png_infop): png_int_32; cdecl;
  png_get_x_offset_microns: function(png_ptr: png_structp; info_ptr: png_infop): png_int_32; cdecl;
  png_get_y_offset_microns: function(png_ptr: png_structp; info_ptr: png_infop): png_int_32; cdecl;

{ Returns pointer to signature string read from PNG header }
  png_get_signature: function(png_ptr: png_structp; info_ptr: png_infop): png_bytep; cdecl;

  
  png_get_bKGD: function(png_ptr: png_structp; info_ptr: png_infop; background: png_color_16pp): png_uint_32; cdecl;
  png_set_bKGD: procedure(png_ptr: png_structp; info_ptr: png_infop; background: png_color_16p); cdecl;

  png_get_cHRM: function(png_ptr: png_structp; info_ptr: png_infop; white_x: pdouble; white_y: pdouble; red_x: pdouble; red_y: pdouble; green_x: pdouble; green_y: pdouble; blue_x: pdouble; blue_y: pdouble): png_uint_32; cdecl;
  png_get_cHRM_fixed: function(png_ptr: png_structp; info_ptr: png_infop; int_white_x: png_fixed_pointp; int_white_y: png_fixed_pointp; int_red_x: png_fixed_pointp; int_red_y: png_fixed_pointp; int_green_x: png_fixed_pointp; int_green_y: png_fixed_pointp; int_blue_x: png_fixed_pointp; int_blue_y: png_fixed_pointp): png_uint_32; cdecl;
  png_set_cHRM: procedure(png_ptr: png_structp; info_ptr: png_infop; white_x: double; white_y: double; red_x: double; red_y: double; green_x: double; green_y: double; blue_x: double; blue_y: double); cdecl;
  png_set_cHRM_fixed: procedure(png_ptr: png_structp; info_ptr: png_infop; int_white_x: png_fixed_point; int_white_y: png_fixed_point; int_red_x: png_fixed_point; int_red_y: png_fixed_point; int_green_x: png_fixed_point; int_green_y: png_fixed_point; int_blue_x: png_fixed_point; int_blue_y: png_fixed_point); cdecl;

  png_get_gAMA: function(png_ptr: png_structp; info_ptr: png_infop; file_gamma: pdouble): png_uint_32; cdecl;
  png_get_gAMA_fixed: function(png_ptr: png_structp; info_ptr: png_infop; int_file_gamma: png_fixed_pointp): png_uint_32; cdecl;
  png_set_gAMA: procedure(png_ptr: png_structp; info_ptr: png_infop; file_gamma: double); cdecl;
  png_set_gAMA_fixed: procedure(png_ptr: png_structp; info_ptr: png_infop; int_file_gamma: png_fixed_point); cdecl;

  png_get_hIST: function(png_ptr: png_structp; info_ptr: png_infop; hist: png_uint_16pp): png_uint_32; cdecl;
  png_set_hIST: procedure(png_ptr: png_structp; info_ptr: png_infop; hist: png_uint_16p); cdecl;
  
  png_get_IHDR: function(png_ptr: png_structp; info_ptr: png_infop; width: png_uint_32p; height: png_uint_32p; bit_depth: pinteger; color_type: pinteger; interlace_method: pinteger; compression_method: pinteger; filter_method: pinteger): png_uint_32; cdecl;
  png_set_IHDR: procedure(png_ptr: png_structp; info_ptr: png_infop; width: png_uint_32; height: png_uint_32; bit_depth: integer; color_type: integer; interlace_method: integer; compression_method: integer; filter_method: integer); cdecl;
  
  png_get_oFFs: function(png_ptr: png_structp; info_ptr: png_infop; offset_x: png_int_32p; offset_y: png_int_32p; unit_type: pinteger): png_uint_32; cdecl;
  png_set_oFFs: procedure(png_ptr: png_structp; info_ptr: png_infop; offset_x: png_int_32; offset_y: png_int_32; unit_type: integer); cdecl;

  png_get_pCAL: function(png_ptr: png_structp; info_ptr: png_infop; purpose: png_charpp; X0: png_int_32p; X1: png_int_32p; _type: pinteger; nparams: pinteger; units: png_charpp; params: png_charppp): png_uint_32; cdecl;
  png_set_pCAL: procedure(png_ptr: png_structp; info_ptr: png_infop; purpose: png_charp; X0: png_int_32; X1: png_int_32; _type: integer; nparams: integer; units: png_charp; params: png_charpp); cdecl;
  
  png_get_pHYs: function(png_ptr: png_structp; info_ptr: png_infop; res_x: png_uint_32p; res_y: png_uint_32p; unit_type: pinteger): png_uint_32; cdecl;
  png_set_pHYs: procedure(png_ptr: png_structp; info_ptr: png_infop; res_x: png_uint_32; res_y: png_uint_32; unit_type: integer); cdecl;

  png_get_PLTE: function(png_ptr: png_structp; info_ptr: png_infop; palette: png_colorpp; num_palette: pinteger): png_uint_32; cdecl;
  png_set_PLTE: procedure(png_ptr: png_structp; info_ptr: png_infop; palette: png_colorp; num_palette: integer) cdecl;

  png_get_sBIT: function(png_ptr: png_structp; info_ptr: png_infop; sig_bit: png_color_8pp): png_uint_32; cdecl;
  png_set_sBIT: procedure(png_ptr: png_structp; info_ptr: png_infop; sig_bit: png_color_8p); cdecl;
  
  png_get_sRGB: function(png_ptr: png_structp; info_ptr: png_infop; intent: pinteger): png_uint_32; cdecl;
  png_set_sRGB: procedure(png_ptr: png_structp; info_ptr: png_infop; intent: integer); cdecl;
  png_set_sRGB_gAMA_and_cHRM: procedure(png_ptr: png_structp; info_ptr: png_infop; intent: integer); cdecl;
  
  png_get_iCCP: function(png_ptr: png_structp; info_ptr: png_infop; name: png_charpp; compression_type: pinteger; profile: png_charpp; proflen: png_uint_32p): png_uint_32; cdecl;
{ Note to maintainer: profile should be png_bytepp }

  png_set_iCCP: procedure(png_ptr: png_structp; info_ptr: png_infop; name: png_charp; compression_type: integer; profile: png_charp; proflen: png_uint_32); cdecl;
{ Note to maintainer: profile should be png_bytep }

  png_get_sPLT: function(png_ptr: png_structp; info_ptr: png_infop; entries: png_sPLT_tpp): png_uint_32; cdecl;
  png_set_sPLT: procedure(png_ptr: png_structp; info_ptr: png_infop; entries: png_sPLT_tp; nentries: integer); cdecl;
  
{ png_get_text also returns the number of text chunks in *num_text }
  png_get_text: function(png_ptr: png_structp; info_ptr: png_infop; text_ptr: png_textpp; num_text: pinteger): png_uint_32; cdecl;
  
{ Note while png_set_text() will accept a structure whose text,
  language, and  translated keywords are NULL pointers, the structure
  returned by png_get_text will always contain regular
  zero-terminated C strings.  They might be empty strings but
  they will never be NULL pointers. }
  png_set_text: procedure(png_ptr: png_structp; info_ptr: png_infop; text_ptr: png_textp; num_text: integer); cdecl;
  
  png_get_tIME: function(png_ptr: png_structp; info_ptr: png_infop; mod_time: png_timepp): png_uint_32; cdecl;
  png_set_tIME: procedure(png_ptr: png_structp; info_ptr: png_infop; mod_time: png_timep); cdecl;
  
  png_get_tRNS: function(png_ptr: png_structp; info_ptr: png_infop; trans: png_bytepp; num_trans: pinteger; trans_values: png_color_16pp): png_uint_32; cdecl;
  png_set_tRNS: procedure(png_ptr: png_structp; info_ptr: png_infop; trans: png_bytep; num_trans: integer; trans_values: png_color_16p); cdecl;

  png_get_sCAL: function(png_ptr: png_structp; info_ptr: png_infop; _unit: pinteger; width: pdouble; height: pdouble): png_uint_32; cdecl;
  png_get_sCAL_s: function(png_ptr: png_structp; info_ptr: png_infop; _unit: pinteger; swidth: png_charpp; sheight: png_charpp): png_uint_32; cdecl;
  png_set_sCAL: procedure(png_ptr: png_structp; info_ptr: png_infop; _unit: integer; width: double; height: double); cdecl;
  png_set_sCAL_s: procedure(png_ptr: png_structp; info_ptr: png_infop; _unit: integer; swidth: png_charp; sheight: png_charp); cdecl;
  
{ provide a list of chunks and how they are to be handled, if the built-in
  handling or default unknown chunk handling is not desired.  Any chunks not
  listed will be handled in the default manner.  The IHDR and IEND chunks
  must not be listed.
     keep = 0: follow default behavour
          = 1: do not keep
          = 2: keep only if safe-to-copy
          = 3: keep even if unsafe-to-copy }
  png_set_keep_unknown_chunks: procedure(png_ptr: png_structp; keep: integer; chunk_list: png_bytep; num_chunks: integer); cdecl;
  png_set_unknown_chunks: procedure(png_ptr: png_structp; info_ptr: png_infop; unknowns: png_unknown_chunkp; num_unknowns: integer); cdecl;
  png_set_unknown_chunk_location: procedure(png_ptr: png_structp; info_ptr: png_infop; chunk: integer; location: integer); cdecl;
  png_get_unknown_chunks: function(png_ptr: png_structp; info_ptr: png_infop; entries: png_unknown_chunkpp): png_uint_32; cdecl;

  png_handle_as_unknown: function(png_ptr: png_structp; chunk_name: png_bytep): integer; cdecl;
  
 
{ Png_free_data() will turn off the "valid" flag for anything it frees.
  If you need to turn it off for a chunk that your application has freed,
  you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); }
  png_set_invalid: procedure(png_ptr: png_structp; info_ptr: png_infop; mask: integer); cdecl;

{ The "params" pointer is currently not used and is for future expansion. }
  png_read_png: procedure(png_ptr: png_structp; info_ptr: png_infop; transforms: integer; params: png_voidp); cdecl;
  png_write_png: procedure(png_ptr: png_structp; info_ptr: png_infop; transforms: integer; params: png_voidp); cdecl;
  

  png_sig_bytes: function: png_bytep; cdecl;

  png_get_copyright: function(png_ptr: png_structp): png_charp; cdecl;
  png_get_header_ver: function(png_ptr: png_structp): png_charp; cdecl;
  png_get_header_version: function(png_ptr: png_structp): png_charp; cdecl;
  png_get_libpng_ver: function(png_ptr: png_structp): png_charp; cdecl;

  png_permit_mng_features: function(png_ptr: png_structp; mng_features_permitted: png_uint_32): png_uint_32; cdecl;

const  
  PNG_HANDLE_CHUNK_AS_DEFAULT   = 0;
  PNG_HANDLE_CHUNK_NEVER        = 1;
  PNG_HANDLE_CHUNK_IF_SAFE      = 2;
  PNG_HANDLE_CHUNK_ALWAYS       = 3;

{ Added to version 1.2.0 }
  PNG_ASM_FLAG_MMX_SUPPORT_COMPILED  = $01;  { not user-settable }
  PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU    = $02;  { not user-settable }
  PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  = $04;
  PNG_ASM_FLAG_MMX_READ_INTERLACE    = $08;
  PNG_ASM_FLAG_MMX_READ_FILTER_SUB   = $10;
  PNG_ASM_FLAG_MMX_READ_FILTER_UP    = $20;
  PNG_ASM_FLAG_MMX_READ_FILTER_AVG   = $40;
  PNG_ASM_FLAG_MMX_READ_FILTER_PAETH = $80;
  PNG_ASM_FLAGS_INITIALIZED          = $80000000;  { not user-settable }

  PNG_MMX_READ_FLAGS = PNG_ASM_FLAG_MMX_READ_COMBINE_ROW or
                       PNG_ASM_FLAG_MMX_READ_INTERLACE   or
                       PNG_ASM_FLAG_MMX_READ_FILTER_SUB  or
                       PNG_ASM_FLAG_MMX_READ_FILTER_UP   or
                       PNG_ASM_FLAG_MMX_READ_FILTER_AVG  or
                       PNG_ASM_FLAG_MMX_READ_FILTER_PAETH;
  PNG_MMX_WRITE_FLAGS = 0;

  PNG_MMX_FLAGS = PNG_ASM_FLAG_MMX_SUPPORT_COMPILED or
                  PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU   or
                  PNG_MMX_READ_FLAGS                or
                  PNG_MMX_WRITE_FLAGS;

  PNG_SELECT_READ   = 1;
  PNG_SELECT_WRITE  = 2;
  

var
  png_get_mmx_flagmask: function(flag_select: integer; compilerID: pinteger): png_uint_32; cdecl;
  png_get_asm_flagmask: function(flag_select: integer): png_uint_32; cdecl;
  png_get_asm_flags: function(png_ptr: png_structp): png_uint_32; cdecl;
  png_get_mmx_bitdepth_threshold: function(png_ptr: png_structp): png_byte; cdecl;
  png_get_mmx_rowbytes_threshold: function(png_ptr: png_structp): png_uint_32; cdecl;
  png_set_asm_flags: procedure(png_ptr: png_structp; asm_flags: png_uint_32); cdecl;
  png_set_mmx_thresholds: procedure(png_ptr: png_structp; mmx_bitdepth_threshold: png_byte; mmx_rowbytes_threshold: png_uint_32); cdecl;
  
  png_mmx_support: function: integer; cdecl;
  
{ Strip the prepended error numbers ("#nnn ") from error and warning
  messages before passing them to the error or warning handler. }
  png_set_strip_error_numbers: procedure(png_ptr: png_structp; strip_mode: png_uint_32); cdecl;
  
  png_set_user_limits: procedure(png_ptr: png_structp; user_width_max: png_uint_32; user_height_max: png_uint_32); cdecl;
  png_get_user_width_max: function(png_ptr: png_structp): png_uint_32; cdecl;
  png_get_user_height_max: function(png_ptr: png_structp): png_uint_32; cdecl;

{ Inline macros to do direct reads of bytes from the input buffer.  These
  require that you are using an architecture that uses PNG byte ordering
  (MSB first) and supports unaligned data storage.  I think that PowerPC
  in big-endian mode and 680x0 are the only ones that will support this.
  The x86 line of processors definitely do not.  The png_get_int_32()
  routine also assumes we are using two's complement format for negative
  values, which is almost certainly true. }
  png_get_uint_32: function(buf: png_bytep): png_uint_32; cdecl;
  png_get_uint_16: function(buf: png_bytep): png_uint_16; cdecl;
  png_get_int_32: function (buf: png_bytep): png_int_32; cdecl;
  png_get_uint_31: function(png_ptr: png_structp; buf: png_bytep): png_uint_32; cdecl;
{ No png_get_int_16 -- may be added if there's a real need for it. }
  
{ Place a 32-bit number into a buffer in PNG byte order (big-endian). }
  png_save_uint_32: procedure(buf: png_bytep; i: png_uint_32); cdecl;
  png_save_int_32: procedure(buf: png_bytep; i: png_int_32); cdecl;

{ Place a 16-bit number into a buffer in PNG byte order.
  The parameter is declared unsigned int, not png_uint_16,
  just to avoid potential problems on pre-ANSI C compilers. }
  png_save_uint_16: procedure(buf: png_bytep; i: word); cdecl;
{ No png_save_int_16 -- may be added if there's a real need for it. }


{ Initialize png_ptr struct for reading, and allocate any other memory.
  (old interface - DEPRECATED - use png_create_read_struct instead). }
  png_read_init: procedure(png_ptr: png_structp); cdecl;

  png_read_init_3: procedure(ptr_ptr: png_structpp; user_png_ver: png_const_charp; png_struct_size: png_size_t); cdecl;
  png_read_init_2: procedure(png_ptr: png_structp; user_png_ver: png_const_charp; png_struct_size: png_size_t; png_info_size: png_size_t); cdecl;

{ Initialize png_ptr struct for writing, and allocate any other memory.
  (old interface - DEPRECATED - use png_create_write_struct instead). }
  png_write_init: procedure(png_ptr: png_structp); cdecl;

  png_write_init_3: procedure(ptr_ptr: png_structpp; user_png_ver: png_const_charp; png_struct_size: png_size_t); cdecl;
  png_write_init_2: procedure(png_ptr: png_structp; user_png_ver: png_const_charp; png_struct_size: png_size_t; png_info_size: png_size_t); cdecl;


const
  {$ifdef win32}
    LIB_PNG_NAME = 'libpng12.dll';
  {$else}
    LIB_PNG_NAME = 'libpng12.so.0';
  {$endif}


  function init_libPNG(libPNG_Name: AnsiString = LIB_PNG_NAME): boolean;
  procedure quit_libPNG;


implementation


var
  libPNG_RefCount: Integer;

  {$ifdef win32}
    libPNG_Handle: cardinal;
  {$else}
    libPNG_Handle: pointer;
  {$endif}


{$ifdef win32}
const
  Kernel32 = 'kernel32.dll';

  function LoadLibrary(lpFileName: pAnsiChar): LongWord; stdcall; external Kernel32 name 'LoadLibraryA';
  function FreeLibrary(hModule: LongWord): LongBool; stdcall; external Kernel32 name 'FreeLibrary';
  function GetProcAddress(hModule: LongWord; lpProcName: pAnsiChar): Pointer; stdcall; external Kernel32 name 'GetProcAddress';
{$else}
const
  libdl = {$IFDEF Linux} 'libdl.so.2'{$ELSE} 'c'{$ENDIF};

  RTLD_LAZY = $001;

  function dlopen(Name: pAnsiChar; Flags: LongInt): Pointer; cdecl; external libdl name 'dlopen';
  function dlclose(Lib: Pointer): LongInt; cdecl; external libdl name 'dlclose';
  function dlsym(Lib: Pointer; Name: pAnsiChar): Pointer; cdecl; external libdl name 'dlsym';
{$endif}


function GetProcAddr(Name: pAnsiChar): Pointer;
begin
  {$ifdef win32}
    GetProcAddr := GetProcAddress(libPNG_Handle, Name);
  {$else}
    GetProcAddr := dlsym(libPNG_Handle, Name);
  {$endif}
end;


function init_libPNG(libPNG_Name: AnsiString): boolean;
var
  Temp: Boolean;
begin
  if (libPNG_RefCount = 0) or (libPNG_Handle = {$ifdef win32} 0 {$else} nil {$endif}) then begin
    if libPNG_Handle = {$ifdef win32} 0 {$else} nil {$endif} then
      {$ifdef win32}
        libPNG_Handle := LoadLibrary(pAnsiChar(libPNG_Name));
      {$else}
        libPNG_Handle := dlopen(pAnsiChar(libPNG_Name), RTLD_LAZY);
      {$endif}

    // load function pointers
    if libPNG_Handle <> {$ifdef win32} 0 {$else} nil {$endif} then begin
      png_access_version_number := GetProcAddr('png_access_version_number');
      png_set_sig_bytes := GetProcAddr('png_set_sig_bytes');
      png_sig_cmp := GetProcAddr('png_sig_cmp');
      png_check_sig := GetProcAddr('png_check_sig');
      png_create_read_struct := GetProcAddr('png_create_read_struct');
      png_create_write_struct := GetProcAddr('png_create_write_struct');
      png_get_compression_buffer_size := GetProcAddr('png_get_compression_buffer_size');
      png_set_compression_buffer_size := GetProcAddr('png_set_compression_buffer_size');
      png_reset_zstream := GetProcAddr('png_reset_zstream');
      png_create_read_struct_2 := GetProcAddr('png_create_read_struct_2');
      png_create_write_struct_2 := GetProcAddr('png_create_write_struct_2');
      png_write_chunk := GetProcAddr('png_write_chunk');
      png_write_chunk_start := GetProcAddr('png_write_chunk_start');
      png_write_chunk_data := GetProcAddr('png_write_chunk_data');
      png_write_chunk_end := GetProcAddr('png_write_chunk_end');
      png_create_info_struct := GetProcAddr('png_create_info_struct');
      png_info_init := GetProcAddr('png_info_init');
      png_info_init_3 := GetProcAddr('png_info_init_3');
      png_write_info_before_PLTE := GetProcAddr('png_write_info_before_PLTE');
      png_write_info := GetProcAddr('png_write_info');
      png_read_info := GetProcAddr('png_read_info');
      png_convert_to_rfc1123 := GetProcAddr('png_convert_to_rfc1123');
      png_convert_from_struct_tm := GetProcAddr('png_convert_from_struct_tm');
      png_convert_from_time_t := GetProcAddr('png_convert_from_time_t');
      png_set_expand := GetProcAddr('png_set_expand');
      png_set_expand_gray_1_2_4_to_8 := GetProcAddr('png_set_expand_gray_1_2_4_to_8');
      png_set_palette_to_rgb := GetProcAddr('png_set_palette_to_rgb');
      png_set_tRNS_to_alpha := GetProcAddr('png_set_tRNS_to_alpha');
      png_set_gray_1_2_4_to_8 := GetProcAddr('png_set_gray_1_2_4_to_8');
      png_set_bgr := GetProcAddr('png_set_bgr');
      png_set_gray_to_rgb := GetProcAddr('png_set_gray_to_rgb');
      png_set_rgb_to_gray := GetProcAddr('png_set_rgb_to_gray');
      png_set_rgb_to_gray_fixed := GetProcAddr('png_set_rgb_to_gray_fixed');
      png_get_rgb_to_gray_status := GetProcAddr('png_get_rgb_to_gray_status');
      png_build_grayscale_palette := GetProcAddr('png_build_grayscale_palette');
      png_set_strip_alpha := GetProcAddr('png_set_strip_alpha');
      png_set_swap_alpha := GetProcAddr('png_set_swap_alpha');
      png_set_invert_alpha := GetProcAddr('png_set_invert_alpha');
      png_set_filler := GetProcAddr('png_set_filler');
      png_set_add_alpha := GetProcAddr('png_set_add_alpha');
      png_set_swap := GetProcAddr('png_set_swap');
      png_set_packing := GetProcAddr('png_set_packing');
      png_set_packswap := GetProcAddr('png_set_packswap');
      png_set_shift := GetProcAddr('png_set_shift');
      png_set_interlace_handling := GetProcAddr('png_set_interlace_handling');
      png_set_invert_mono := GetProcAddr('png_set_invert_mono');
      png_set_background := GetProcAddr('png_set_background');
      png_set_strip_16 := GetProcAddr('png_set_strip_16');
      png_set_dither := GetProcAddr('png_set_dither');
      png_set_gamma := GetProcAddr('png_set_gamma');
      png_permit_empty_plte := GetProcAddr('png_permit_empty_plte');
      png_set_flush := GetProcAddr('png_set_flush');
      png_write_flush := GetProcAddr('png_write_flush');
      png_start_read_image := GetProcAddr('png_start_read_image');
      png_read_update_info := GetProcAddr('png_read_update_info');
      png_read_rows := GetProcAddr('png_read_rows');
      png_read_row := GetProcAddr('png_read_row');
      png_read_image := GetProcAddr('png_read_image');
      png_write_row := GetProcAddr('png_write_row');
      png_write_rows := GetProcAddr('png_write_rows');
      png_write_image := GetProcAddr('png_write_image');
      png_write_end := GetProcAddr('png_write_end');
      png_read_end := GetProcAddr('png_read_end');
      png_destroy_info_struct := GetProcAddr('png_destroy_info_struct');
      png_destroy_read_struct := GetProcAddr('png_destroy_read_struct');
      png_destroy_write_struct := GetProcAddr('png_destroy_write_struct');
      png_set_crc_action := GetProcAddr('png_set_crc_action');
      png_set_filter := GetProcAddr('png_set_filter');
      png_set_filter_heuristics := GetProcAddr('png_set_filter_heuristics');
      png_set_compression_level := GetProcAddr('png_set_compression_level');
      png_set_compression_mem_level := GetProcAddr('png_set_compression_mem_level');
      png_set_compression_strategy := GetProcAddr('png_set_compression_strategy');
      png_set_compression_window_bits := GetProcAddr('png_set_compression_window_bits');
      png_set_compression_method := GetProcAddr('png_set_compression_method');
      png_init_io := GetProcAddr('png_init_io');
      png_set_error_fn := GetProcAddr('png_set_error_fn');
      png_get_error_ptr := GetProcAddr('png_get_error_ptr');
      png_set_write_fn := GetProcAddr('png_set_write_fn');
      png_set_read_fn := GetProcAddr('png_set_read_fn');
      png_get_io_ptr := GetProcAddr('png_get_io_ptr');
      png_set_read_status_fn := GetProcAddr('png_set_read_status_fn');
      png_set_write_status_fn := GetProcAddr('png_set_write_status_fn');
      png_set_mem_fn := GetProcAddr('png_set_mem_fn');
      png_get_mem_ptr := GetProcAddr('png_get_mem_ptr');
      png_set_read_user_transform_fn := GetProcAddr('png_set_read_user_transform_fn');
      png_set_write_user_transform_fn := GetProcAddr('png_set_write_user_transform_fn');
      png_set_user_transform_info := GetProcAddr('png_set_user_transform_info');
      png_get_user_transform_ptr := GetProcAddr('png_get_user_transform_ptr');
      png_set_read_user_chunk_fn := GetProcAddr('png_set_read_user_chunk_fn');
      png_get_user_chunk_ptr := GetProcAddr('png_get_user_chunk_ptr');
      png_set_progressive_read_fn := GetProcAddr('png_set_progressive_read_fn');
      png_get_progressive_ptr := GetProcAddr('png_get_progressive_ptr');
      png_process_data := GetProcAddr('png_process_data');
      png_progressive_combine_row := GetProcAddr('png_progressive_combine_row');
      png_malloc := GetProcAddr('png_malloc');
      png_malloc_warn := GetProcAddr('png_malloc_warn');
      png_free := GetProcAddr('png_free');
      png_zalloc := GetProcAddr('png_zalloc');
      png_zfree := GetProcAddr('png_zfree');
      png_free_data := GetProcAddr('png_free_data');
      png_data_freer := GetProcAddr('png_data_freer');
      png_malloc_default := GetProcAddr('png_malloc_default');
      png_free_default := GetProcAddr('png_free_default');
      png_memcpy_check := GetProcAddr('png_memcpy_check');
      png_memset_check := GetProcAddr('png_memset_check');
      png_far_to_near := GetProcAddr('png_far_to_near');
      png_error := GetProcAddr('png_error');
      png_chunk_error := GetProcAddr('png_chunk_error');
      png_warning := GetProcAddr('png_warning');
      png_chunk_warning := GetProcAddr('png_chunk_warning');
      png_get_valid := GetProcAddr('png_get_valid');
      png_get_rowbytes := GetProcAddr('png_get_rowbytes');
      png_get_rows := GetProcAddr('png_get_rows');
      png_set_rows := GetProcAddr('png_set_rows');
      png_get_channels := GetProcAddr('png_get_channels');
      png_get_image_width := GetProcAddr('png_get_image_width');
      png_get_image_height := GetProcAddr('png_get_image_height');
      png_get_bit_depth := GetProcAddr('png_get_bit_depth');
      png_get_color_type := GetProcAddr('png_get_color_type');
      png_get_filter_type := GetProcAddr('png_get_filter_type');
      png_get_interlace_type := GetProcAddr('png_get_interlace_type');
      png_get_compression_type := GetProcAddr('png_get_compression_type');
      png_get_pixels_per_meter := GetProcAddr('png_get_pixels_per_meter');
      png_get_x_pixels_per_meter := GetProcAddr('png_get_x_pixels_per_meter');
      png_get_y_pixels_per_meter := GetProcAddr('png_get_y_pixels_per_meter');
      png_get_pixel_aspect_ratio := GetProcAddr('png_get_pixel_aspect_ratio');
      png_get_x_offset_pixels := GetProcAddr('png_get_x_offset_pixels');
      png_get_y_offset_pixels := GetProcAddr('png_get_y_offset_pixels');
      png_get_x_offset_microns := GetProcAddr('png_get_x_offset_microns');
      png_get_y_offset_microns := GetProcAddr('png_get_y_offset_microns');
      png_get_signature := GetProcAddr('png_get_signature');
      png_get_bKGD := GetProcAddr('png_get_bKGD');
      png_set_bKGD := GetProcAddr('png_set_bKGD');
      png_get_cHRM := GetProcAddr('png_get_cHRM');
      png_get_cHRM_fixed := GetProcAddr('png_get_cHRM_fixed');
      png_set_cHRM := GetProcAddr('png_set_cHRM');
      png_set_cHRM_fixed := GetProcAddr('png_set_cHRM_fixed');
      png_get_gAMA := GetProcAddr('png_get_gAMA');
      png_get_gAMA_fixed := GetProcAddr('png_get_gAMA_fixed');
      png_set_gAMA := GetProcAddr('png_set_gAMA');
      png_set_gAMA_fixed := GetProcAddr('png_set_gAMA_fixed');
      png_get_hIST := GetProcAddr('png_get_hIST');
      png_set_hIST := GetProcAddr('png_set_hIST');
      png_get_IHDR := GetProcAddr('png_get_IHDR');
      png_set_IHDR := GetProcAddr('png_set_IHDR');
      png_get_oFFs := GetProcAddr('png_get_oFFs');
      png_set_oFFs := GetProcAddr('png_set_oFFs');
      png_get_pCAL := GetProcAddr('png_get_pCAL');
      png_set_pCAL := GetProcAddr('png_set_pCAL');
      png_get_pHYs := GetProcAddr('png_get_pHYs');
      png_set_pHYs := GetProcAddr('png_set_pHYs');
      png_get_PLTE := GetProcAddr('png_get_PLTE');
      png_set_PLTE := GetProcAddr('png_set_PLTE');
      png_get_sBIT := GetProcAddr('png_get_sBIT');
      png_set_sBIT := GetProcAddr('png_set_sBIT');
      png_get_sRGB := GetProcAddr('png_get_sRGB');
      png_set_sRGB := GetProcAddr('png_set_sRGB');
      png_set_sRGB_gAMA_and_cHRM := GetProcAddr('png_set_sRGB_gAMA_and_cHRM');
      png_get_iCCP := GetProcAddr('png_get_iCCP');
      png_set_iCCP := GetProcAddr('png_set_iCCP');
      png_get_sPLT := GetProcAddr('png_get_sPLT');
      png_set_sPLT := GetProcAddr('png_set_sPLT');
      png_get_text := GetProcAddr('png_get_text');
      png_set_text := GetProcAddr('png_set_text');
      png_get_tIME := GetProcAddr('png_get_tIME');
      png_set_tIME := GetProcAddr('png_set_tIME');
      png_get_tRNS := GetProcAddr('png_get_tRNS');
      png_set_tRNS := GetProcAddr('png_set_tRNS');
      png_get_sCAL := GetProcAddr('png_get_sCAL');
      png_get_sCAL_s := GetProcAddr('png_get_sCAL_s');
      png_set_sCAL := GetProcAddr('png_set_sCAL');
      png_set_sCAL_s := GetProcAddr('png_set_sCAL_s');
      png_set_keep_unknown_chunks := GetProcAddr('png_set_keep_unknown_chunks');
      png_set_unknown_chunks := GetProcAddr('png_set_unknown_chunks');
      png_set_unknown_chunk_location := GetProcAddr('png_set_unknown_chunk_location');
      png_get_unknown_chunks := GetProcAddr('png_get_unknown_chunks');
      png_handle_as_unknown := GetProcAddr('png_handle_as_unknown');
      png_set_invalid := GetProcAddr('png_set_invalid');
      png_read_png := GetProcAddr('png_read_png');
      png_write_png := GetProcAddr('png_write_png');
      png_sig_bytes := GetProcAddr('png_sig_bytes');
      png_get_copyright := GetProcAddr('png_get_copyright');
      png_get_header_ver := GetProcAddr('png_get_header_ver');
      png_get_header_version := GetProcAddr('png_get_header_version');
      png_get_libpng_ver := GetProcAddr('png_get_libpng_ver');
      png_permit_mng_features := GetProcAddr('png_permit_mng_features');
      png_get_mmx_flagmask := GetProcAddr('png_get_mmx_flagmask');
      png_get_asm_flagmask := GetProcAddr('png_get_asm_flagmask');
      png_get_asm_flags := GetProcAddr('png_get_asm_flags');
      png_get_mmx_bitdepth_threshold := GetProcAddr('png_get_mmx_bitdepth_threshold');
      png_get_mmx_rowbytes_threshold := GetProcAddr('png_get_mmx_rowbytes_threshold');
      png_set_asm_flags := GetProcAddr('png_set_asm_flags');
      png_set_mmx_thresholds := GetProcAddr('png_set_mmx_thresholds');
      png_mmx_support := GetProcAddr('png_mmx_support');
      png_set_strip_error_numbers := GetProcAddr('png_set_strip_error_numbers');
      png_set_user_limits := GetProcAddr('png_set_user_limits');
      png_get_user_width_max := GetProcAddr('png_get_user_width_max');
      png_get_user_height_max := GetProcAddr('png_get_user_height_max');
      png_get_uint_32 := GetProcAddr('png_get_uint_32');
      png_get_uint_16 := GetProcAddr('png_get_uint_16');
      png_get_int_32 := GetProcAddr('png_get_int_32');
      png_get_uint_31 := GetProcAddr('png_get_uint_31');
      png_save_uint_32 := GetProcAddr('png_save_uint_32');
      png_save_int_32 := GetProcAddr('png_save_int_32');
      png_save_uint_16 := GetProcAddr('png_save_uint_16');
      png_read_init := GetProcAddr('png_read_init');
      png_read_init_3 := GetProcAddr('png_read_init_3');
      png_read_init_2 := GetProcAddr('png_read_init_2');
      png_write_init := GetProcAddr('png_write_init');
      png_write_init_3 := GetProcAddr('png_write_init_3');
      png_write_init_2 := GetProcAddr('png_write_init_2');
    end;
  end;

  // check pointers
  Temp :=
    (libPNG_Handle <> {$ifdef win32} 0 {$else} nil {$endif}) ;
(*
    (Addr(png_access_version_number) <> nil) and
    (Addr(png_set_sig_bytes) <> nil) and
    (Addr(png_sig_cmp) <> nil) and
    (Addr(png_check_sig) <> nil) and
    (Addr(png_create_read_struct) <> nil) and
    (Addr(png_create_write_struct) <> nil) and
    (Addr(png_get_compression_buffer_size) <> nil) and
    (Addr(png_set_compression_buffer_size) <> nil) and
    (Addr(png_reset_zstream) <> nil) and
    (Addr(png_create_read_struct_2) <> nil) and
    (Addr(png_create_write_struct_2) <> nil) and
    (Addr(png_write_chunk) <> nil) and
    (Addr(png_write_chunk_start) <> nil) and
    (Addr(png_write_chunk_data) <> nil) and
    (Addr(png_write_chunk_end) <> nil) and
    (Addr(png_create_info_struct) <> nil) and
    (Addr(png_info_init) <> nil) and
    (Addr(png_info_init_3) <> nil) and
    (Addr(png_write_info_before_PLTE) <> nil) and
    (Addr(png_write_info) <> nil) and
    (Addr(png_read_info) <> nil) and
    (Addr(png_convert_to_rfc1123) <> nil) and
    (Addr(png_convert_from_struct_tm) <> nil) and
    (Addr(png_convert_from_time_t) <> nil) and
    (Addr(png_set_expand) <> nil) and
    (Addr(png_set_expand_gray_1_2_4_to_8) <> nil) and
    (Addr(png_set_palette_to_rgb) <> nil) and
    (Addr(png_set_tRNS_to_alpha) <> nil) and
    (Addr(png_set_gray_1_2_4_to_8) <> nil) and
    (Addr(png_set_bgr) <> nil) and
    (Addr(png_set_gray_to_rgb) <> nil) and
    (Addr(png_set_rgb_to_gray) <> nil) and
    (Addr(png_set_rgb_to_gray_fixed) <> nil) and
    (Addr(png_get_rgb_to_gray_status) <> nil) and
    (Addr(png_build_grayscale_palette) <> nil) and
    (Addr(png_set_strip_alpha) <> nil) and
    (Addr(png_set_swap_alpha) <> nil) and
    (Addr(png_set_invert_alpha) <> nil) and
    (Addr(png_set_filler) <> nil) and
    (Addr(png_set_add_alpha) <> nil) and
    (Addr(png_set_swap) <> nil) and
    (Addr(png_set_packing) <> nil) and
    (Addr(png_set_packswap) <> nil) and
    (Addr(png_set_shift) <> nil) and
    (Addr(png_set_interlace_handling) <> nil) and
    (Addr(png_set_invert_mono) <> nil) and
    (Addr(png_set_background) <> nil) and
    (Addr(png_set_strip_16) <> nil) and
    (Addr(png_set_dither) <> nil) and
    (Addr(png_set_gamma) <> nil) and
    (Addr(png_permit_empty_plte) <> nil) and
    (Addr(png_set_flush) <> nil) and
    (Addr(png_write_flush) <> nil) and
    (Addr(png_start_read_image) <> nil) and
    (Addr(png_read_update_info) <> nil) and
    (Addr(png_read_rows) <> nil) and
    (Addr(png_read_row) <> nil) and
    (Addr(png_read_image) <> nil) and
    (Addr(png_write_row) <> nil) and
    (Addr(png_write_rows) <> nil) and
    (Addr(png_write_image) <> nil) and
    (Addr(png_write_end) <> nil) and
    (Addr(png_read_end) <> nil) and
    (Addr(png_destroy_info_struct) <> nil) and
    (Addr(png_destroy_read_struct) <> nil) and
    (Addr(png_destroy_write_struct) <> nil) and
    (Addr(png_set_crc_action) <> nil) and
    (Addr(png_set_filter) <> nil) and
    (Addr(png_set_filter_heuristics) <> nil) and
    (Addr(png_set_compression_level) <> nil) and
    (Addr(png_set_compression_mem_level) <> nil) and
    (Addr(png_set_compression_strategy) <> nil) and
    (Addr(png_set_compression_window_bits) <> nil) and
    (Addr(png_set_compression_method) <> nil) and
    (Addr(png_init_io) <> nil) and
    (Addr(png_set_error_fn) <> nil) and
    (Addr(png_get_error_ptr) <> nil) and
    (Addr(png_set_write_fn) <> nil) and
    (Addr(png_set_read_fn) <> nil) and
    (Addr(png_get_io_ptr) <> nil) and
    (Addr(png_set_read_status_fn) <> nil) and
    (Addr(png_set_write_status_fn) <> nil) and
    (Addr(png_set_mem_fn) <> nil) and
    (Addr(png_get_mem_ptr) <> nil) and
    (Addr(png_set_read_user_transform_fn) <> nil) and
    (Addr(png_set_write_user_transform_fn) <> nil) and
    (Addr(png_set_user_transform_info) <> nil) and
    (Addr(png_get_user_transform_ptr) <> nil) and
    (Addr(png_set_read_user_chunk_fn) <> nil) and
    (Addr(png_get_user_chunk_ptr) <> nil) and
    (Addr(png_set_progressive_read_fn) <> nil) and
    (Addr(png_get_progressive_ptr) <> nil) and
    (Addr(png_process_data) <> nil) and
    (Addr(png_progressive_combine_row) <> nil) and
    (Addr(png_malloc) <> nil) and
    (Addr(png_malloc_warn) <> nil) and
    (Addr(png_free) <> nil) and
    (Addr(png_zalloc) <> nil) and
    (Addr(png_zfree) <> nil) and
    (Addr(png_free_data) <> nil) and
    (Addr(png_data_freer) <> nil) and
    (Addr(png_malloc_default) <> nil) and
    (Addr(png_free_default) <> nil) and
    (Addr(png_memcpy_check) <> nil) and
    (Addr(png_memset_check) <> nil) and
    (Addr(png_far_to_near) <> nil) and
    (Addr(png_error) <> nil) and
    (Addr(png_chunk_error) <> nil) and
    (Addr(png_warning) <> nil) and
    (Addr(png_chunk_warning) <> nil) and
    (Addr(png_get_valid) <> nil) and
    (Addr(png_get_rowbytes) <> nil) and
    (Addr(png_get_rows) <> nil) and
    (Addr(png_set_rows) <> nil) and
    (Addr(png_get_channels) <> nil) and
    (Addr(png_get_image_width) <> nil) and
    (Addr(png_get_image_height) <> nil) and
    (Addr(png_get_bit_depth) <> nil) and
    (Addr(png_get_color_type) <> nil) and
    (Addr(png_get_filter_type) <> nil) and
    (Addr(png_get_interlace_type) <> nil) and
    (Addr(png_get_compression_type) <> nil) and
    (Addr(png_get_pixels_per_meter) <> nil) and
    (Addr(png_get_x_pixels_per_meter) <> nil) and
    (Addr(png_get_y_pixels_per_meter) <> nil) and
    (Addr(png_get_pixel_aspect_ratio) <> nil) and
    (Addr(png_get_x_offset_pixels) <> nil) and
    (Addr(png_get_y_offset_pixels) <> nil) and
    (Addr(png_get_x_offset_microns) <> nil) and
    (Addr(png_get_y_offset_microns) <> nil) and
    (Addr(png_get_signature) <> nil) and
    (Addr(png_get_bKGD) <> nil) and
    (Addr(png_set_bKGD) <> nil) and
    (Addr(png_get_cHRM) <> nil) and
    (Addr(png_get_cHRM_fixed) <> nil) and
    (Addr(png_set_cHRM) <> nil) and
    (Addr(png_set_cHRM_fixed) <> nil) and
    (Addr(png_get_gAMA) <> nil) and
    (Addr(png_get_gAMA_fixed) <> nil) and
    (Addr(png_set_gAMA) <> nil) and
    (Addr(png_set_gAMA_fixed) <> nil) and
    (Addr(png_get_hIST) <> nil) and
    (Addr(png_set_hIST) <> nil) and
    (Addr(png_get_IHDR) <> nil) and
    (Addr(png_set_IHDR) <> nil) and
    (Addr(png_get_oFFs) <> nil) and
    (Addr(png_set_oFFs) <> nil) and
    (Addr(png_get_pCAL) <> nil) and
    (Addr(png_set_pCAL) <> nil) and
    (Addr(png_get_pHYs) <> nil) and
    (Addr(png_set_pHYs) <> nil) and
    (Addr(png_get_PLTE) <> nil) and
    (Addr(png_set_PLTE) <> nil) and
    (Addr(png_get_sBIT) <> nil) and
    (Addr(png_set_sBIT) <> nil) and
    (Addr(png_get_sRGB) <> nil) and
    (Addr(png_set_sRGB) <> nil) and
    (Addr(png_set_sRGB_gAMA_and_cHRM) <> nil) and
    (Addr(png_get_iCCP) <> nil) and
    (Addr(png_set_iCCP) <> nil) and
    (Addr(png_get_sPLT) <> nil) and
    (Addr(png_set_sPLT) <> nil) and
    (Addr(png_get_text) <> nil) and
    (Addr(png_set_text) <> nil) and
    (Addr(png_get_tIME) <> nil) and
    (Addr(png_set_tIME) <> nil) and
    (Addr(png_get_tRNS) <> nil) and
    (Addr(png_set_tRNS) <> nil) and
    (Addr(png_get_sCAL) <> nil) and
    (Addr(png_get_sCAL_s) <> nil) and
    (Addr(png_set_sCAL) <> nil) and
    (Addr(png_set_sCAL_s) <> nil) and
    (Addr(png_set_keep_unknown_chunks) <> nil) and
    (Addr(png_set_unknown_chunks) <> nil) and
    (Addr(png_set_unknown_chunk_location) <> nil) and
    (Addr(png_get_unknown_chunks) <> nil) and
    (Addr(png_handle_as_unknown) <> nil) and
    (Addr(png_set_invalid) <> nil) and
    (Addr(png_read_png) <> nil) and
    (Addr(png_write_png) <> nil) and
    (Addr(png_sig_bytes) <> nil) and
    (Addr(png_get_copyright) <> nil) and
    (Addr(png_get_header_ver) <> nil) and
    (Addr(png_get_header_version) <> nil) and
    (Addr(png_get_libpng_ver) <> nil) and
    (Addr(png_permit_mng_features) <> nil) and
    (Addr(png_get_mmx_flagmask) <> nil) and
    (Addr(png_get_asm_flagmask) <> nil) and
    (Addr(png_get_asm_flags) <> nil) and
    (Addr(png_get_mmx_bitdepth_threshold) <> nil) and
    (Addr(png_get_mmx_rowbytes_threshold) <> nil) and
    (Addr(png_set_asm_flags) <> nil) and
    (Addr(png_set_mmx_thresholds) <> nil) and
    (Addr(png_mmx_support) <> nil) and
    (Addr(png_set_strip_error_numbers) <> nil) and
    (Addr(png_set_user_limits) <> nil) and
    (Addr(png_get_user_width_max) <> nil) and
    (Addr(png_get_user_height_max) <> nil) and
    (Addr(png_get_uint_32) <> nil) and
    (Addr(png_get_uint_16) <> nil) and
    (Addr(png_get_int_32) <> nil) and
    (Addr(png_get_uint_31) <> nil) and
    (Addr(png_save_uint_32) <> nil) and
    (Addr(png_save_int_32) <> nil) and
    (Addr(png_save_uint_16) <> nil) and
    (Addr(png_read_init) <> nil) and
    (Addr(png_read_init_3) <> nil) and
    (Addr(png_read_init_2) <> nil) and
    (Addr(png_write_init) <> nil) and
    (Addr(png_write_init_3) <> nil) and
    (Addr(png_write_init_2) <> nil);
*)

  if Temp then
    Inc(libPNG_RefCount);

  Result := Temp;
end;


procedure quit_libPNG;
begin
  Dec(libPNG_RefCount);

  if libPNG_RefCount <= 0 then begin
    if libPNG_Handle <> {$ifdef win32} 0 {$else} nil {$endif} then begin
      {$ifdef win32}
        FreeLibrary(libPNG_Handle);
        libPNG_Handle := 0;
      {$else}
        dlclose(libPNG_Handle);
        libPNG_Handle := nil;
      {$endif}
    end;

    png_access_version_number := nil;
    png_set_sig_bytes := nil;
    png_sig_cmp := nil;
    png_check_sig := nil;
    png_create_read_struct := nil;
    png_create_write_struct := nil;
    png_get_compression_buffer_size := nil;
    png_set_compression_buffer_size := nil;
    png_reset_zstream := nil;
    png_create_read_struct_2 := nil;
    png_create_write_struct_2 := nil;
    png_write_chunk := nil;
    png_write_chunk_start := nil;
    png_write_chunk_data := nil;
    png_write_chunk_end := nil;
    png_create_info_struct := nil;
    png_info_init := nil;
    png_info_init_3 := nil;
    png_write_info_before_PLTE := nil;
    png_write_info := nil;
    png_read_info := nil;
    png_convert_to_rfc1123 := nil;
    png_convert_from_struct_tm := nil;
    png_convert_from_time_t := nil;
    png_set_expand := nil;
    png_set_expand_gray_1_2_4_to_8 := nil;
    png_set_palette_to_rgb := nil;
    png_set_tRNS_to_alpha := nil;
    png_set_gray_1_2_4_to_8 := nil;
    png_set_bgr := nil;
    png_set_gray_to_rgb := nil;
    png_set_rgb_to_gray := nil;
    png_set_rgb_to_gray_fixed := nil;
    png_get_rgb_to_gray_status := nil;
    png_build_grayscale_palette := nil;
    png_set_strip_alpha := nil;
    png_set_swap_alpha := nil;
    png_set_invert_alpha := nil;
    png_set_filler := nil;
    png_set_add_alpha := nil;
    png_set_swap := nil;
    png_set_packing := nil;
    png_set_packswap := nil;
    png_set_shift := nil;
    png_set_interlace_handling := nil;
    png_set_invert_mono := nil;
    png_set_background := nil;
    png_set_strip_16 := nil;
    png_set_dither := nil;
    png_set_gamma := nil;
    png_permit_empty_plte := nil;
    png_set_flush := nil;
    png_write_flush := nil;
    png_start_read_image := nil;
    png_read_update_info := nil;
    png_read_rows := nil;
    png_read_row := nil;
    png_read_image := nil;
    png_write_row := nil;
    png_write_rows := nil;
    png_write_image := nil;
    png_write_end := nil;
    png_read_end := nil;
    png_destroy_info_struct := nil;
    png_destroy_read_struct := nil;
    png_destroy_write_struct := nil;
    png_set_crc_action := nil;
    png_set_filter := nil;
    png_set_filter_heuristics := nil;
    png_set_compression_level := nil;
    png_set_compression_mem_level := nil;
    png_set_compression_strategy := nil;
    png_set_compression_window_bits := nil;
    png_set_compression_method := nil;
    png_init_io := nil;
    png_set_error_fn := nil;
    png_get_error_ptr := nil;
    png_set_write_fn := nil;
    png_set_read_fn := nil;
    png_get_io_ptr := nil;
    png_set_read_status_fn := nil;
    png_set_write_status_fn := nil;
    png_set_mem_fn := nil;
    png_get_mem_ptr := nil;
    png_set_read_user_transform_fn := nil;
    png_set_write_user_transform_fn := nil;
    png_set_user_transform_info := nil;
    png_get_user_transform_ptr := nil;
    png_set_read_user_chunk_fn := nil;
    png_get_user_chunk_ptr := nil;
    png_set_progressive_read_fn := nil;
    png_get_progressive_ptr := nil;
    png_process_data := nil;
    png_progressive_combine_row := nil;
    png_malloc := nil;
    png_malloc_warn := nil;
    png_free := nil;
    png_zalloc := nil;
    png_zfree := nil;
    png_free_data := nil;
    png_data_freer := nil;
    png_malloc_default := nil;
    png_free_default := nil;
    png_memcpy_check := nil;
    png_memset_check := nil;
    png_far_to_near := nil;
    png_error := nil;
    png_chunk_error := nil;
    png_warning := nil;
    png_chunk_warning := nil;
    png_get_valid := nil;
    png_get_rowbytes := nil;
    png_get_rows := nil;
    png_set_rows := nil;
    png_get_channels := nil;
    png_get_image_width := nil;
    png_get_image_height := nil;
    png_get_bit_depth := nil;
    png_get_color_type := nil;
    png_get_filter_type := nil;
    png_get_interlace_type := nil;
    png_get_compression_type := nil;
    png_get_pixels_per_meter := nil;
    png_get_x_pixels_per_meter := nil;
    png_get_y_pixels_per_meter := nil;
    png_get_pixel_aspect_ratio := nil;
    png_get_x_offset_pixels := nil;
    png_get_y_offset_pixels := nil;
    png_get_x_offset_microns := nil;
    png_get_y_offset_microns := nil;
    png_get_signature := nil;
    png_get_bKGD := nil;
    png_set_bKGD := nil;
    png_get_cHRM := nil;
    png_get_cHRM_fixed := nil;
    png_set_cHRM := nil;
    png_set_cHRM_fixed := nil;
    png_get_gAMA := nil;
    png_get_gAMA_fixed := nil;
    png_set_gAMA := nil;
    png_set_gAMA_fixed := nil;
    png_get_hIST := nil;
    png_set_hIST := nil;
    png_get_IHDR := nil;
    png_set_IHDR := nil;
    png_get_oFFs := nil;
    png_set_oFFs := nil;
    png_get_pCAL := nil;
    png_set_pCAL := nil;
    png_get_pHYs := nil;
    png_set_pHYs := nil;
    png_get_PLTE := nil;
    png_set_PLTE := nil;
    png_get_sBIT := nil;
    png_set_sBIT := nil;
    png_get_sRGB := nil;
    png_set_sRGB := nil;
    png_set_sRGB_gAMA_and_cHRM := nil;
    png_get_iCCP := nil;
    png_set_iCCP := nil;
    png_get_sPLT := nil;
    png_set_sPLT := nil;
    png_get_text := nil;
    png_set_text := nil;
    png_get_tIME := nil;
    png_set_tIME := nil;
    png_get_tRNS := nil;
    png_set_tRNS := nil;
    png_get_sCAL := nil;
    png_get_sCAL_s := nil;
    png_set_sCAL := nil;
    png_set_sCAL_s := nil;
    png_set_keep_unknown_chunks := nil;
    png_set_unknown_chunks := nil;
    png_set_unknown_chunk_location := nil;
    png_get_unknown_chunks := nil;
    png_handle_as_unknown := nil;
    png_set_invalid := nil;
    png_read_png := nil;
    png_write_png := nil;
    png_sig_bytes := nil;
    png_get_copyright := nil;
    png_get_header_ver := nil;
    png_get_header_version := nil;
    png_get_libpng_ver := nil;
    png_permit_mng_features := nil;
    png_get_mmx_flagmask := nil;
    png_get_asm_flagmask := nil;
    png_get_asm_flags := nil;
    png_get_mmx_bitdepth_threshold := nil;
    png_get_mmx_rowbytes_threshold := nil;
    png_set_asm_flags := nil;
    png_set_mmx_thresholds := nil;
    png_mmx_support := nil;
    png_set_strip_error_numbers := nil;
    png_set_user_limits := nil;
    png_get_user_width_max := nil;
    png_get_user_height_max := nil;
    png_get_uint_32 := nil;
    png_get_uint_16 := nil;
    png_get_int_32 := nil;
    png_get_uint_31 := nil;
    png_save_uint_32 := nil;
    png_save_int_32 := nil;
    png_save_uint_16 := nil;
    png_read_init := nil;
    png_read_init_3 := nil;
    png_read_init_2 := nil;
    png_write_init := nil;
    png_write_init_3 := nil;
    png_write_init_2 := nil;
  end;
end;

procedure pngReadFn(png_ptr: png_structp; Data: png_bytep; length: png_size_t);
var
  fs: TStream;
begin
  fs := TStream(png_get_io_ptr(png_ptr));
  Assert(Assigned(Data), 'Attempt to read from null file pointer');
  fs.Read(Data^, length);
end;

procedure pngWriteFn(png_ptr: png_structp; Data: png_bytep; length: png_size_t);
var
  fs: TStream;
begin
  fs := TStream(png_get_io_ptr(png_ptr));
  Assert(Assigned(Data), 'Attempt to write to null file pointer');
  fs.Write(Data^, length);
end;

procedure pngErrorFn(struct: png_structp; str: png_const_charp); cdecl;
begin
{$IFDEF GLS_LOGGING}
  GLSLogger.Log(string(str), lkError);
{$ENDIF}
end;

procedure pngWarnFn(struct: png_structp; str: png_const_charp); cdecl;
begin
{$IFDEF GLS_LOGGING}
  GLSLogger.Log(string(str), lkWarning);
{$ENDIF}
end;

end.